如果执行带有返回值的SQL语句,则不返回游标查询

时间:2014-10-20 02:16:23

标签: 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
    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。

2 个答案:

答案 0 :(得分:3)

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

INSERT into aTable (aField)
OUTPUT Inserted.ID 
Values ('SomeValue')

如果您的桌子上有触发器,则必须为OUTPUT

定义目标表
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;

答案 1 :(得分:3)

我使用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'的字段。请求。