首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多语句Delphi TZquery (Zeos)错误

多语句Delphi TZquery (Zeos)错误
EN

Stack Overflow用户
提问于 2013-05-26 12:45:59
回答 4查看 9K关注 0票数 5

我试图做一个像这样的多个语句查询:

代码语言:javascript
复制
// 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;

我收到了以下错误信息: server :您的SQL语法出现了错误;请检查与您的MySQL服务器版本对应的手册,以便在第2行使用接近“插入客户端(名称、年龄)值”(“doe”、“21”)的正确语法;

我已经检查了手册,TZQuery和TZUpdateSql(来自zeos lib )提供了在内部执行多个并发语句的可能性。

编辑解题

谢谢GregD,在运行了几个测试之后,事务对我来说很好!这就是我将来用来帮助别人的方法。

代码语言:javascript
复制
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为True时,事务将在每次执行SQL语句后自动执行,但您可以使用StartTransaction命令来防止这种自动执行,直到您明确地调用Commit为止。

AutoCommit为False时,不应调用StartTransaction。然后事务会自动启动,但它不会在每个执行语句之后自动提交。

StartTransaction 过程StartTransaction过程在连接的数据库中启动一个新事务。只有当AutoCommit属性为TRUE时,才应该使用它。每当您试图将AutoCommit设置为false时调用它,就会引发一个SInvalidOpInNonAutoCommit。这种行为是预期的,因为StartTransaction应该用作AutoCommit模式的转义。当您调用StartTransaction时,AutoCommit将被“关闭”,然后,当您调用提交或回滚时,AutoCommit将再次“打开”。如果将AutoCommit设置为false,则会自动创建新事务,并选择如何关闭它们(提交或回滚)。

过程提交提交当前语句到数据库。只应在非AutoCommit模式下使用(在该模式下,每个语句都是自动完成的,使此过程毫无用处),或者当您处于AutoCommit模式并希望完成由StartTransaction过程打开的事务时。注释完成当前事务(如果有)。如果您不想将您的饱和文件保存到数据库中,则应该使用回滚过程。

procedure Rollback回滚当前事务中所有以前的语句。只应在非AutoCommit模式下使用(在该模式下,每个语句都是自动完成的,使此过程毫无用处),或者当您处于AutoCommit模式并希望完成由StartTransaction过程打开的事务时。如果存在,回滚将完成当前事务。如果您不想松开您的饱和,您应该使用提交过程。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-05-26 12:59:13

试试这段代码,如果出现同样的问题,请告诉我们:

代码语言:javascript
复制
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查询的处理速度,就像它在一个批处理中所做的那样,而不是两次。

编辑#1:

我不是Zeos方面的专家,但是对于其他语言,您可以一个一个地执行查询:

代码语言:javascript
复制
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;

编辑#2:事务

关于堆栈溢出的一个问题有许多关于在MySQL中使用事务的好例子。尽管这些示例是为PHP编写的,但我相信您可以在那里找到一些好的指针。确保MySQL服务器上的表是InnoDB而不是MyISAM

票数 2
EN

Stack Overflow用户

发布于 2013-05-26 16:34:48

我不知道Zeos和多个语句,但这并不是真正的问题。您的查询(SQL注入)和执行它们的缓慢方法(不能缓存和重用的串接字符串)造成了一个主要的安全问题。

如果正确地停止使用字符串连接来形成查询,而是使用参数化语句,则根本不需要担心多个语句:

代码语言:javascript
复制
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;

现在,查询将运行得更快(因为DBMS可以编译它一次并多次重用它(我提到的“缓存”),您不再需要SQL注入风险,并且不再需要多个语句。

票数 5
EN

Stack Overflow用户

发布于 2013-05-26 13:43:57

我也不是ZEOS方面的专家,但是看看来源,你把TZUpdateSQLMultiStatements属性设置为true了吗?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16759373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档