Некалькі аператараў Delphi TZquery (Zeos) памылка

ім спрабуюць зрабіць некалькі запытаў заявы, як гэта:

// without the second insert the query works fine.
// i need 2 querys to work because later, i'll do inserts on different kind of tables.
// that's why i need 2 querys, not a single query which insert 2 records.   

with ZQuery1 do
    begin
        SQL.Clear;
        SQL.Add('insert into client (name,age) values ('+QuotedStr('john')+','+QuotedStr('20')+');');
        SQL.Add('insert into client (name,age) values ('+QuotedStr('doe')+','+QuotedStr('21')+');');
        ExecSQL;
    end;

я атрымаў паведамленне пра памылку: Памылка SQL: У вас памылка ў вашым SQL сінтаксісу; праверце кіраўніцтва, якое адпавядае версіі сервера MySQL для правільнага сінтаксісу, каб выкарыстоўваць побач з «уставіць кліент (імя, узрост) VALUES (» лані «" 21 ")» у радку 2;

я ўжо праверыць ўручную, кампаненты TZQuery і TZUpdateSql (ад Zeos ОМТ) даюць магчымасць выканаць некалькі аператараў, ўнутрана.

EDIT [вырашана]

Дзякуй GregD, пасля запуску некалькіх тэстаў, аперацыі выдатна працуе для мяне! вось як я выкарыстоўваю, каб дапамагчы іншым у будучыні.

try
    ZConnection.AutoCommit := True;
    ZConnection.StartTransaction;

    With ZQuery Do
    begin
        SQL.Clear;
        SQL.Add('insert into clients (name,age) values ('+QuotedStr('john')+','+QuotedStr('20')+')');
        ExecSQL;
        SQL.Clear;
        SQL.Add('insert into clients (name,age) values ('+QuotedStr('doe')+','+QuotedStr('21')+')');
        ExecSQL;
    end;

    ZConnection.Commit; 
except
    ZConnection.Rollback
end;

<�Моцны> Гэта як AutoCommit ўласцівасць на самай справе працуе ў Zeos:

калі <�моцны> AutoCommit праўдзіва, то аперацыі здзяйсняюцца аўтаматычна пасля кожнага выкананага аператара SQL, але вы можаце выкарыстоўваць каманду StartTransaction відавочна для прадухілення гэтага аўто здзяйснялі, пакуль вы відавочна не выклічаце Commit ,

калі <�моцны> AutoCommit з'яўляецца False, то вы не павінны называць StartTransaction. Тады транзакцыя запускаецца аўтаматычна, але яна не будзе здзяйсняць аўтаматычна пасля кожнага выкананага аператара.

procedure StartTransaction The StartTransaction procedure starts a new transaction within the connected database. It should be only used when AutoCommit property is TRUE. Whenever you try to call it with AutoCommit set to false, an SInvalidOpInNonAutoCommit will be raised. This behaviour is expected, as StartTransaction should be used as a escape to the AutoCommit mode. When you call StartTransaction, the AutoCommit is "turned off", and then, when you call Commit or Rollback, the AutoCommit is "turned on" again. If you're working with AutoCommit set to false, new transactions are created automatically and you choose how you will close them (Commit or Rollback).

procedure Commit Commit current statements to the database. Should be used only in non-AutoCommit mode (where every statement is auto-commited, making this procedure useless) or when you are in AutoCommit mode and want to finish a transaction opened by StartTransaction procedure. Commiting finishes the current transaction, if there's any. If you don't want to save your satatements to the database, you should use the Rollback procedure.

procedure Rollback Rolls back all previous statements in current transaction. Should be used only in non-AutoCommit mode (where every statement is auto-commited, making this procedure useless) or when you are in AutoCommit mode and want to finish a transaction opened by StartTransaction procedure. The Rollback finishes the current transaction, if there's any. If you don't want to loose your satatements, you should use the Commit procedure.

4
Ўстаўце Ці гэтая праца без другога?
дададзена аўтар itsols, крыніца
OT: калі вы выпрабоўваеце Enterprise, Ultimate або Architect выданне Delphi або RAD Studio, паспрабуйце FireDAC .
дададзена аўтар TLama, крыніца
Я заўсёды задаюся пытаннем, хто быў настолькі дурны, што ініцыяваў гэты пачварны SQL.Clear; SQL.Add (...); шаблон замест кароткага SQL.Text: = '...' . Як і ўсе нямыя рэчы да смешнага даўгавечныя.
дададзена аўтар Fr0sT, крыніца
ды, без другі ўстаўкі ён працуе як шарм :)
дададзена аўтар Rebelss, крыніца

6 адказы

Я паняцця не маю, пра Zeos і некалькіх аператараў, але гэта на самай справе не праблема. Вы выклікалі вялікую праблему бяспекі з вашым запытам (ін'екцыі SQL) і павольным спосабам выканання іх усіх (счэпленыя радкамі, якія не могуць быць кэшуюцца і паўторна выкарыстоўваць).

Калі вы правільна спыніць выкарыстоўваць канкатэнацыяй, каб сфармаваць свае запыты, і выкарыстоўваць параметризованные інструкцыі замест гэтага, вам не трэба турбавацца аб шматлікіх заявах на ўсё:

with ZQuery1 do
begin
  SQL.Clear;
  SQL.Add('insert into client (name,age)');
  SQL.Add('values (:Name, :Age);'
  ParamByName('Name').AsString := 'John';
  ParamByName('Age').AsInteger := 20;
  ExecSQL;
  ParamByName('Name').AsString := 'Doe';
  ParamByName('Age').AsInteger :- 21;
  ExecSQL;
end;

Запыт цяпер будзе працаваць хутчэй (таму што СКБД можа скампіляваць яго адзін раз і выкарыстоўваць яго некалькі разоў (далей «кэшаванне» я згадаў), вы не маеце рызыку ін'екцыі SQL больш працяглы перыяд часу, а таксама шматлікія заявы, больш не трэба.

5
дададзена
@SAMPro: Гэта будзе залежаць. Вы павінны былі б праверыць гэта самастойна. SQL скампіляваны і кэшуюцца пасля першага выканання, так што адзіная частка, якая зменіць б значэння параметраў. Я падазраю, што было б даволі хутка, асабліва калі вы толькі ўставіць пару радкоў. Калі вы робіце шмат радкоў, я думаю, пытанне прадукцыйнасці стварэння SQL і параметраў і запаўненне іх будзе некалькі павольна, як добра. Як звычайна, адказ: бенчмарк іх самастойна параўноўваць, выкарыстоўваючы свае ўласныя дадзеныя і апаратныя сродкі, і вырашыць, што лепш працуе для вас.
дададзена аўтар Ken White, крыніца
@SAMPro: Як я ўжо сказаў (і будзе паўтарацца для вас): Як звычайна, адказ: <�я> бенчмарк іх самастойна параўноўваць, выкарыстоўваючы свае ўласныя дадзеныя і апаратныя сродкі, і вырашыць, што лепш працуе для вас .
дададзена аўтар Ken White, крыніца
+1, лепшы адказ да гэтага часу, як вы звяртаецеся як праблему OP, а таксама іншыя патэнцыйныя праблемы.
дададзена аўтар Guillem Vicens, крыніца
Ці з'яўляецца гэта роўна ўставіць у кліенце (імя, узрост) значэнняў (: Name1 ,: Age1), (: Name2 ,: Возраст2) у тэрмін хуткасці?
дададзена аўтар SAMPro, крыніца
Я сумняваюся, што аб прадукцыйнасці MySQL боку. З Урой рашэннем MySQL трэба напрыклад для блакавання табліцы некалькі разоў, але калі вы рыхтуеце і Exec адзін запыт, гэта будзе значна хутчэй. І вы маеце рацыю, для ўстаўкі пару радкоў яе не розныя.
дададзена аўтар SAMPro, крыніца

Я паняцця не маю, пра Zeos і некалькіх аператараў, але гэта на самай справе не праблема. Вы выклікалі вялікую праблему бяспекі з вашым запытам (ін'екцыі SQL) і павольным спосабам выканання іх усіх (счэпленыя радкамі, якія не могуць быць кэшуюцца і паўторна выкарыстоўваць).

Калі вы правільна спыніць выкарыстоўваць канкатэнацыяй, каб сфармаваць свае запыты, і выкарыстоўваць параметризованные інструкцыі замест гэтага, вам не трэба турбавацца аб шматлікіх заявах на ўсё:

with ZQuery1 do
begin
  SQL.Clear;
  SQL.Add('insert into client (name,age)');
  SQL.Add('values (:Name, :Age);'
  ParamByName('Name').AsString := 'John';
  ParamByName('Age').AsInteger := 20;
  ExecSQL;
  ParamByName('Name').AsString := 'Doe';
  ParamByName('Age').AsInteger :- 21;
  ExecSQL;
end;

Запыт цяпер будзе працаваць хутчэй (таму што СКБД можа скампіляваць яго адзін раз і выкарыстоўваць яго некалькі разоў (далей «кэшаванне» я згадаў), вы не маеце рызыку ін'екцыі SQL больш працяглы перыяд часу, а таксама шматлікія заявы, больш не трэба.

5
дададзена
@SAMPro: Як я ўжо сказаў (і будзе паўтарацца для вас): Як звычайна, адказ: <�я> бенчмарк іх самастойна параўноўваць, выкарыстоўваючы свае ўласныя дадзеныя і апаратныя сродкі, і вырашыць, што лепш працуе для вас .
дададзена аўтар Ken White, крыніца
@SAMPro: Гэта будзе залежаць. Вы павінны былі б праверыць гэта самастойна. SQL скампіляваны і кэшуюцца пасля першага выканання, так што адзіная частка, якая зменіць б значэння параметраў. Я падазраю, што было б даволі хутка, асабліва калі вы толькі ўставіць пару радкоў. Калі вы робіце шмат радкоў, я думаю, пытанне прадукцыйнасці стварэння SQL і параметраў і запаўненне іх будзе некалькі павольна, як добра. Як звычайна, адказ: бенчмарк іх самастойна параўноўваць, выкарыстоўваючы свае ўласныя дадзеныя і апаратныя сродкі, і вырашыць, што лепш працуе для вас.
дададзена аўтар Ken White, крыніца
+1, лепшы адказ да гэтага часу, як вы звяртаецеся як праблему OP, а таксама іншыя патэнцыйныя праблемы.
дададзена аўтар Guillem Vicens, крыніца
Ці з'яўляецца гэта роўна ўставіць у кліенце (імя, узрост) значэнняў (: Name1 ,: Age1), (: Name2 ,: Возраст2) у тэрмін хуткасці?
дададзена аўтар SAMPro, крыніца
Я сумняваюся, што аб прадукцыйнасці MySQL боку. З Урой рашэннем MySQL трэба напрыклад для блакавання табліцы некалькі разоў, але калі вы рыхтуеце і Exec адзін запыт, гэта будзе значна хутчэй. І вы маеце рацыю, для ўстаўкі пару радкоў яе не розныя.
дададзена аўтар SAMPro, крыніца

Я паняцця не маю, пра Zeos і некалькіх аператараў, але гэта на самай справе не праблема. Вы выклікалі вялікую праблему бяспекі з вашым запытам (ін'екцыі SQL) і павольным спосабам выканання іх усіх (счэпленыя радкамі, якія не могуць быць кэшуюцца і паўторна выкарыстоўваць).

Калі вы правільна спыніць выкарыстоўваць канкатэнацыяй, каб сфармаваць свае запыты, і выкарыстоўваць параметризованные інструкцыі замест гэтага, вам не трэба турбавацца аб шматлікіх заявах на ўсё:

with ZQuery1 do
begin
  SQL.Clear;
  SQL.Add('insert into client (name,age)');
  SQL.Add('values (:Name, :Age);'
  ParamByName('Name').AsString := 'John';
  ParamByName('Age').AsInteger := 20;
  ExecSQL;
  ParamByName('Name').AsString := 'Doe';
  ParamByName('Age').AsInteger :- 21;
  ExecSQL;
end;

Запыт цяпер будзе працаваць хутчэй (таму што СКБД можа скампіляваць яго адзін раз і выкарыстоўваць яго некалькі разоў (далей «кэшаванне» я згадаў), вы не маеце рызыку ін'екцыі SQL больш працяглы перыяд часу, а таксама шматлікія заявы, больш не трэба.

5
дададзена
@SAMPro: Як я ўжо сказаў (і будзе паўтарацца для вас): Як звычайна, адказ: <�я> бенчмарк іх самастойна параўноўваць, выкарыстоўваючы свае ўласныя дадзеныя і апаратныя сродкі, і вырашыць, што лепш працуе для вас .
дададзена аўтар Ken White, крыніца
@SAMPro: Гэта будзе залежаць. Вы павінны былі б праверыць гэта самастойна. SQL скампіляваны і кэшуюцца пасля першага выканання, так што адзіная частка, якая зменіць б значэння параметраў. Я падазраю, што было б даволі хутка, асабліва калі вы толькі ўставіць пару радкоў. Калі вы робіце шмат радкоў, я думаю, пытанне прадукцыйнасці стварэння SQL і параметраў і запаўненне іх будзе некалькі павольна, як добра. Як звычайна, адказ: бенчмарк іх самастойна параўноўваць, выкарыстоўваючы свае ўласныя дадзеныя і апаратныя сродкі, і вырашыць, што лепш працуе для вас.
дададзена аўтар Ken White, крыніца
+1, лепшы адказ да гэтага часу, як вы звяртаецеся як праблему OP, а таксама іншыя патэнцыйныя праблемы.
дададзена аўтар Guillem Vicens, крыніца
Ці з'яўляецца гэта роўна ўставіць у кліенце (імя, узрост) значэнняў (: Name1 ,: Age1), (: Name2 ,: Возраст2) у тэрмін хуткасці?
дададзена аўтар SAMPro, крыніца
Я сумняваюся, што аб прадукцыйнасці MySQL боку. З Урой рашэннем MySQL трэба напрыклад для блакавання табліцы некалькі разоў, але калі вы рыхтуеце і Exec адзін запыт, гэта будзе значна хутчэй. І вы маеце рацыю, для ўстаўкі пару радкоў яе не розныя.
дададзена аўтар SAMPro, крыніца

Паспрабуйце гэты код і дайце нам ведаць, калі ўзнікне такая ж праблема:

with ZQuery1 do
begin
    SQL.Clear;
    SQL.Add('insert into client (name,age) values ('+QuotedStr('john')+','+QuotedStr('20')+'),('+QuotedStr('doe')+','+QuotedStr('21')+');');
    ExecSQL;
end;

Такім чынам, вы можаце таксама паскорыць апрацоўку дадзеных MySQL гэтага INSERT запыту, як гэта робіць у адной партыі, а не ў два разы.

<�Моцны> EDIT # 1:

Я не эксперт у Zeos, але і з іншымі мовамі, вы маглі б паспрабаваць выканаць запыт па адным:

with ZQuery1 do
    begin
        SQL.Clear;
        SQL.Add('insert into client (name,age) values ('+QuotedStr('john')+','+QuotedStr('20')+');');
        ExecSQL;
        SQL.Clear;
        SQL.Add('insert into client (name,age) values ('+QuotedStr('doe')+','+QuotedStr('21')+');');
        ExecSQL;
    end;

EDIT #2: Transactions

One question on Stackoverflow has many good examples about using transactions in MySQL. Although, the examples are written for PHP, I'm sure you could find some good pointers there. Make sure that your tables on the MySQL server are InnoDB not MyISAM.

3
дададзена
@Rebelss Я не эксперт, але Zeos ад паняццяў, я не думаю, што Mulitple запыт ўстаўкі б вырашыць праблему страты злучэння. Хутчэй за ўсё, як GregD прапанаваў, выкарыстоўваючы транзакцыю здаецца найбольш прыдатным. І з аперацыямі на месцы, гэта не мае значэння, нават калі б яны былі некалькі аператараў Execute.
дададзена аўтар itsols, крыніца
Ваш адказ з'яўляецца працаздольным і добра, але пытанне аб выкарыстанні некалькіх аператараў ўстаўкі ... Але добрая спроба :)
дададзена аўтар itsols, крыніца
Добрае пытанне. Я згодзен. Я на самой справе было гэтае пытаньне сам і не быў упэўнены, што, калі некалькі запытаў былі падтрыманы з Zeos. У мяне няма на маім Linux OS прама зараз, каб праверыць. Ці працуе шматразовы запыт з ім? Проста цікава. Дзякуй! О, і +1 за адказ.
дададзена аўтар itsols, крыніца
@Rebelss Я разумею, што адказ GregD не з'яўляецца менавіта тое, што вы глядзелі. Але ці ёсць прычына, чаму вы не можаце проста стварыць яшчэ адзін аператар запыту і выканаць яго? Ёсць значны выйгрыш пры спробе запусціць 2 запытаў у адным выканаць заяву? Проста думаць услых
дададзена аўтар itsols, крыніца
Так, але яго DBA, верагодна, аддаюць перавагу некалькі радкоў INSERT заяву ;-)
дададзена аўтар GregD, крыніца
@Rebelss, чаму тады не выкарыстоўваць транзакцыі? Здзелкі ACID падатная і хацелі б пераканацца, што выкананне ў поўным аб'ёме.
дададзена аўтар GregD, крыніца
На жаль GregD, ваш адказ добры, але мне трэба 2 querys працаваць, таму што пазней, я буду рабіць ўстаўкі на рознага роду табліц. Вось чаму мне трэба 2 querys, ні адзін запыт, ўстаўце 2 запісаў.
дададзена аўтар Rebelss, крыніца
@itsols так, ёсць прычына, з шматлікімі карамі, ёсць магчымасць страты злучэння Інтэрнэт паміж карамі. то некаторыя пакарання не будзе завершана, і гэта непрымальна.
дададзена аўтар Rebelss, крыніца
@itsols, дзякуй вам таксама, як гэта было прапанавана GregD, выкарыстоўваючы транзакцыі выдатна працуе для мяне.
дададзена аўтар Rebelss, крыніца

Я не эксперт у ZEOS небудзь, але, гледзячы на ​​ крыніца , вы задалі MultiStatements ўласцівасць TZUpdateSQL ісціна?

1
дададзена

Вы спрабавалі TZSQLProcessor? Кажа, што кампанент быў зроблены для такіх патрэбаў (як у блоку ZSqlProcessor.pas):

{**
  Implements a unidatabase component which parses and executes SQL Scripts.
}
0
дададзена