使用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中是否不允许“打开”操作。我应该使用什么方法? (我们必须在项目中使用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上,最优雅的方法可能是使用
OUTPUT Clause
如果是多部分插入,则不仅可以返回一个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可以防止cursor not returned query错误并提供预期的结果:

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 - 如果使用返回值执行SQL语句,则不返回游标查询,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26457659/

10-11 22:25
查看更多