我有一个带有Generator的firebird 2.x数据库和一个生成关键字段的触发器。 我需要从下面的查询中获取返回的值。
INSERT INTO XXXX (vdate,description) values ('"+ VDate +"','"+ Description +"') returning vno INTO :ParamVoucherNo
我尝试了以下代码的几个版本,但它没有破坏,我得到了
动态sql错误sql错误代码= -104
是否真的可以使用TIBQuery在delphi中获取返回值?
Query1->SQL->Clear();
Query1->SQL->Add("INSERT INTO XXXX (vodate,description) values ('"+ VDate +"','"+ Description +"') returning vno INTO :ParamVoucherNo");
Query1->Params->ParamByName("ParamVoucherno")->ParamType = ptResult;
Query1->Params->ParamByName("ParamVoucherno")->DataType = ftInteger;
Query1->Params->ParamByName("ParamVoucherno")->Value = "";
Query1->Prepare();
Query1->ExecSQL();
有什么建议吗?
答案 0 :(得分:5)
来自Firebird README.returning:
INTO部分(即变量列表)仅允许在PSQL中使用(到 分配局部变量)并在DSQL中被拒绝。
由于IBX使用DSQL,您应该从查询中排除INTO
部分。
INSERT ... RETURNING
看起来与调用存储过程相同,后者返回结果集。因此,您必须使用Open
代替ExecSQL
。
答案 1 :(得分:3)
将动态SQL与参数混合起来只是令人困惑。
请改为:
Query1->SQL->Clear();
Query1->SQL->Add("INSERT INTO table1 (vodate,description) VALUES"+
"(:VoDate,:Description) RETURNING vno INTO :VoucherNo ");
Query1->Params->ParamByName("VoDate")->Value = VDate;
Query1->Params->ParamByName("description")->Value = Description;
Query1->Prepare();
Query1->ExecSQL();
VoucherNo = Query1->Params->ParamByName("VoucherNo")->AsInteger;
答案 2 :(得分:2)
使用Delphi 6我使用EXECUTE BLOCK语句成功返回ID:
EXECUTE BLOCK
RETURNS ( DeptKey INT )
AS
BEGIN
INSERT INTO DEPARTMENT
( COMPANY_KEY, DEPARTMENT_NAME )
VALUES ( 1, 'TEST1' ) RETURNING DEPARTMENT_KEY INTO :DeptKey;
SUSPEND;
END;
从Delphi您可以进行以下操作:
FQuery.SQL.Text := '<Execute Block Statement>';
FQuery.Open();
ANewKey := FQuery.Fields[0].AsInteger;
答案 3 :(得分:1)
为什么不首先获取VoucherNo的下一个值,然后是
"INSERT INTO table1 (vno, vodate,description) VALUES (:VoucherNo,:VoDate,:Description)");
然后可以省略你的触发器(这很好),或者修改为检测null(或者&lt; = 0也可以使用),然后只填充vno字段。
create trigger bi_mytable
active before insert position 1
on mytable
as
begin
if (new.vno is null)
then new.vno = next value for gen_VoucherNos;
end
客户端你可以:
select gen_id(gen_VoucherNos, 1) from rdb$database;
通过以这种方式修改触发器,如果/当您想要插入记录块时,您可以稍后解决此问题
答案 4 :(得分:1)
IBX不是Firebird准备好的
您可以查看支持Firebird功能的FIBPLUS
FIBPlus还支持FB2.0插入......进入...返回。轮到你了 不应该为从客户端获取生成器值而烦恼 将它们留在触发器中。您还可以使用RDB $ DB_KEY。新的可能 插入返回和RDB $ DB_KEY的工作变体显示在 例如“FB2InsertReturning”。
答案 5 :(得分:1)
我想知道INSERT
是否可以包含在EXECUTE BLOCK
命令中。
那么IBX会管理EXECUTE BLOCK
吗?
希望在XE2中的IBX和Unified Interbase中尝试
PS:即使没有,我找到了这个库,它告诉我们在Delphi XE2的IBX(x86和x64)上工作并添加EXECUTE BLOCK
支持:http://www.loginovprojects.ru/index.php?page=ibxfbutils#eb。< / p>
答案 6 :(得分:0)
据我所知,IBX应该有一些变化。内部INSERT ... RETURNING
的处理方式应与返回参数的可选程序相同。
答案 7 :(得分:0)
我知道很久以前就回答了这个问题,但我必须尽可能清楚地写出这个问题,对于那些需要这个问题的人来说。
我也需要&#34; INSERT..RETURNING&#34;事情。 Delphi让我疯了很长时间,直到我改变了我的数据访问组件。 我甚至因此而从Delphi XE2转移到XE5 ......
结论:IBX不支持退货! FireDAC对于我需要的Firebird来说是完美的。
转移到FireDAC,您将能够完成所需的一切,并且性能卓越。
答案 8 :(得分:0)
如果你有一个包含这两个字段的表:GRP_NO和GROUPNAME,并且你想获得新的GRP_NO,你必须使用 RET _ 作为前缀,参见示例:
procedure TFormDatenbank.Button1Click(Sender: TObject);
var
q: Uni.TUniQuery;
ID: Integer;
GroupName: String;
begin
GroupName := 'MyGroupName';
q := TUniQuery.Create(nil);
try
q.Connection := Datenmodul.UniConnection;
q.ParamCheck := true; // the default value of ParamCheck is true.
q.SQL.Clear;
q.SQL.Add('SELECT GRP_NO, GROUPNAME FROM GROUPDATA WHERE GROUPNAME = :GROUPNAME');
q.ParamByName('GROUPNAME').AsString := GroupName;
q.Open;
if q.RecordCount > 0 then
ID := q.FieldByName('GRP_NO').AsInteger
else
begin
// there exist no group with this name, so insert this new name
q.SQL.Clear;
q.SQL.Add('INSERT INTO GROUPDATA');
q.SQL.Add('(GROUPNAME)');
q.SQL.Add('VALUES');
q.SQL.Add('(:GROUPNAME)');
q.SQL.Add('RETURNING GRP_NO;');
q.ParamByName('GROUPNAME').AsString := GroupName;
q.Execute;
ID := q.ParamByName('RET_GRP_NO').AsInteger;
end;
finally
q.Free;
end;
end;
答案 9 :(得分:0)
从IBx2来源,您可以这样做:
//Uses IBSql;
//var Cur: IResults;
IBSQL1.SQL.Text := 'delete from tbl_document where id = 120 returning id;';
IBSQL1.Prepare;
if IBSQL1.Prepared then
begin
Cur := IBSQL1.Statement.Execute(IBTransaction1.TransactionIntf);
WriteLn(Cur.Data[cou].AsString);
Cur.GetTransaction.Commit(True);
end;
IResults接口代码:
IResults = interface
function getCount: integer;
function GetTransaction: ITransaction;
function ByName(Idx: String): ISQLData;
function getSQLData(index: integer): ISQLData;
procedure GetData(index: integer; var IsNull:boolean; var len: short; var data: PChar);
procedure SetRetainInterfaces(aValue: boolean);
property Data[index: integer]: ISQLData read getSQLData; default;
property Count: integer read getCount;
end;
测试环境: Arch Linux X86 火鸟3 拉撒路1.9 FPC 3.0.4 快速说明:这适用于IBX中的新Firebird API,但我没有使用IBX在Legacy Firebird API中测试它。