Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如果使用返回值执行SQL语句,则不返回游标查询_Sql Server_Delphi_Dbexpress - Fatal编程技术网

Sql server 如果使用返回值执行SQL语句,则不返回游标查询

Sql server 如果使用返回值执行SQL语句,则不返回游标查询,sql-server,delphi,dbexpress,Sql Server,Delphi,Dbexpress,在使用DBExpress和Delphi XE执行下面的查询时,我遇到了一个问题。我需要从执行的查询中获取最后一个标识id: function TServerDBUtils.ExecuteQueryWithIdentity(ASQLConn: TSQLConnection): Integer; var newSQLQuery: TSQLQuery; begin Result := -1; newSQLQuery := TSQLQuery.Create(nil); try

在使用DBExpress和Delphi XE执行下面的查询时,我遇到了一个问题。我需要从执行的查询中获取最后一个标识id:

function TServerDBUtils.ExecuteQueryWithIdentity(ASQLConn: TSQLConnection): Integer;
var
  newSQLQuery: TSQLQuery;
begin
  Result := -1;  
  newSQLQuery := TSQLQuery.Create(nil);
  try
    with newSQLQuery do
    begin
      SQLConnection := ASQLConn;

      SQL.Clear;
      SQL.Add('Insert into SampleTable(uomname) values(' + Quotedstr('bag') +')';

      SQL.Add('Select Scope_Identity()');
      Open;
      Result:= Fields[0].AsInteger;     
    end;
  finally
    FreeAndNil(newSQLQuery);
  end;
end;
我得到一个错误游标未返回查询。我以前使用过相同的方法,使用FireDac和Delphi XE5,没有出现错误。不,我想知道在DBExpress中是否不允许open做这样的事情。我应该用什么方法?我们必须在项目中使用DBExpress 我试过这个:

function TServerDBUtils.ExecuteQueryWithIdentity(ASQLConn: TSQLConnection): Integer;
var
  newSQLQuery: TSQLQuery;
begin
  Result := -1;  
  newSQLQuery := TSQLQuery.Create(nil);
  try
    with newSQLQuery do
    begin
      SQLConnection := ASQLConn;

      SQL.Clear;
      SQL.Add('Insert into SampleTable(uomname) values(' + Quotedstr('bag') +')';
      ExecSQL;

      SQL.Clear;
      SQL.Add('Select Scope_Identity()');
      Open;
      Result:= Fields[0].AsInteger;     
    end;
  finally
    FreeAndNil(newSQLQuery);
  end;
end;
并且总是得到空值,可能是因为不同的会话。 对不起,我的英语不好,提前谢谢你的帮助

更新: 如果我们使用@@identity:

SQL.Add('Insert into SampleTable(uomname) values(' + Quotedstr('bag') +')';
ExecSQL;

SQL.Clear;
SQL.Add('Select @@Identity');
Open;
Result:= Fields[0].AsInteger; 

但是,正如SQLServer所说的那样,存在一个问题,即如果该表在Insert时触发了触发器,则返回值是该触发器插入的表的最后一个ID。

SQL Server上最优雅的方法可能是使用 在多部分插入的情况下,它不仅能够返回一个ID,而且能够返回所有新生成的ID

INSERT into aTable (aField)
OUTPUT Inserted.ID 
Values ('SomeValue')
如果表上有触发器,则必须为输出定义目标表

DECLARE @tmp table (ID int)
INSERT into aTable (aField)
OUTPUT Inserted.ID into @tmp 
Values ('SomeValue')
Select * from @tmp
另一个建议是使用参数而不是硬编码值

使用TSQLQuery,在语句之前添加SET NOCOUNT ON将防止游标未返回查询错误,并传递预期结果:

begin
  SQLQuery1.SQL.text :='SET NOCOUNT ON'
                +#13#10'DECLARE @tmp table (ID int)'
                +#13#10'INSERT into aTable (aField)'
                +#13#10'OUTPUT Inserted.ID into @tmp'
                +#13#10'Values (:P)'
                +#13#10'Select * from @tmp';
  SQLQuery1.Params.ParamByName('P').Value := 'SomeText';
  SQLQuery1.Open;
  Showmessage(SQLQuery1.Fields[0].asString);
end;

SQL Server上最优雅的方式可能是使用 在多部分插入的情况下,它不仅能够返回一个ID,而且能够返回所有新生成的ID

INSERT into aTable (aField)
OUTPUT Inserted.ID 
Values ('SomeValue')
如果表上有触发器,则必须为输出定义目标表

DECLARE @tmp table (ID int)
INSERT into aTable (aField)
OUTPUT Inserted.ID into @tmp 
Values ('SomeValue')
Select * from @tmp
另一个建议是使用参数而不是硬编码值

使用TSQLQuery,在语句之前添加SET NOCOUNT ON将防止游标未返回查询错误,并传递预期结果:

begin
  SQLQuery1.SQL.text :='SET NOCOUNT ON'
                +#13#10'DECLARE @tmp table (ID int)'
                +#13#10'INSERT into aTable (aField)'
                +#13#10'OUTPUT Inserted.ID into @tmp'
                +#13#10'Values (:P)'
                +#13#10'Select * from @tmp';
  SQLQuery1.Params.ParamByName('P').Value := 'SomeText';
  SQLQuery1.Open;
  Showmessage(SQLQuery1.Fields[0].asString);
end;

我使用XE2和SQL Server来实现这一点

with newSQLQuery do
try      
  SQLConnection := ASQLConn;
  SQL.Clear;
  SQL.Add('Insert into SampleTable(uomname) values(' + Quotedstr('bag') +')');
  ExecSQL;

  SQL.Clear;
  SQL.Add('Select Scope_Identity() as id');
  Open;

  if not Eof then
     Result := FieldByName('id').asInteger;
finally
  FreeAndNil(newSQLQuery);
end;

因此,我在第二条SQL语句中引入as关键字。打开查询时,只需检查请求的名称为“id”的字段。

我使用XE2和SQL Server来完成此操作

with newSQLQuery do
try      
  SQLConnection := ASQLConn;
  SQL.Clear;
  SQL.Add('Insert into SampleTable(uomname) values(' + Quotedstr('bag') +')');
  ExecSQL;

  SQL.Clear;
  SQL.Add('Select Scope_Identity() as id');
  Open;

  if not Eof then
     Result := FieldByName('id').asInteger;
finally
  FreeAndNil(newSQLQuery);
end;

因此,我在第二条SQL语句中引入as关键字。当我打开查询时,只需检查请求的名称为“id”的字段。

谢谢,问题仍然是TSQLQuery it self。我们必须使用TSQLQuery.Open从查询中检索任何返回。但是TSQLQuery.Open不允许我们执行insert、update等操作。我们将得到错误游标not returned查询。TSQLQuery.ExecSQL可以执行insert、update等,但没有任何返回值。如果我们使用ExecSQL后跟Open,则由于作用域不同,它不起作用。CMIIW非常感谢,解决方案是“不计数”。我们已尝试使用SQL Server连接属性,并将“NO COUNT”设为选中=true。但它不起作用。但当我们使用您的解决方案时:在主SQL之前添加'SET NOCOUNT ON',然后再添加Select scope\u identity,这种方法是有效的。我们也会尝试您的建议,我们会尝试在我们的类中添加output Inserted.ID和generate。谢谢您,问题仍然是TSQLQuery it self。我们必须使用TSQLQuery.Open从查询中检索任何返回。但是TSQLQuery.Open不允许我们执行insert、update等操作。我们将得到错误游标not returned查询。TSQLQuery.ExecSQL可以执行insert、update等,但没有任何返回值。如果我们使用ExecSQL后跟Open,则由于作用域不同,它不起作用。CMIIW非常感谢,解决方案是“不计数”。我们已尝试使用SQL Server连接属性,并将“NO COUNT”设为选中=true。但它不起作用。但当我们使用您的解决方案时:在主SQL之前添加'SET NOCOUNT ON',然后再添加Select scope\u identity,这种方法是有效的。我们也会尝试您的建议,我们会尝试在类中添加output Inserted.ID和generate。使用存储过程会让您的生活更轻松。使用存储过程会让您的生活更轻松。谢谢,我尝试了您的解决方案,但返回值始终为0。可能是因为ExecSQL和Open是同一个会话,但作用域不同。所以你的身份不起作用。如果我们使用@标识,我们将得到结果,因为它将读取任何范围,但如果表中有触发器插入到其他表中,我们将得到错误的结果。谢谢,我尝试了您的解决方案,但返回值始终为0。可能是因为ExecSQL和Open是同一个会话,但作用域不同。所以你的身份不起作用。如果我们使用@标识,我们将得到结果,因为它将读取任何范围,但如果表中有一个触发器插入到另一个表中,我们将得到错误的结果。