我正在运行通过FireDAC连接的IB数据库。
以下动态查询有效:
INSERT INTO RELATIONS (C_ID, M_ID, A_ID)
SELECT c.C_ID, 0, a.A_ID
FROM CATEGORIES c, ACTIONS a
WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION
我向RELATIONS A_INDEX
(整数)添加了一列。对于这个专栏,我想提供一个参数,所以我这样做:
INSERT INTO RELATIONS (C_ID, M_ID, A_ID, A_INDEX)
SELECT c.C_ID, 0, a.A_ID, :A_INDEX
FROM CATEGORIES c, ACTIONS a
WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION
然而,这不起作用。由于某种原因,当我执行查询时,它会抱怨CATEGORY
param存在转换错误。
这是此查询操作的完整代码:
procedure Test;
var
Query: TFDQuery;
begin
Query := TFDQuery.Create(nil);
try
Query.Connection := DBDataModule.dbMain;
Query.ResourceOptions.ParamCreate := False;
Query.SQL.BeginUpdate;
Query.SQL.Add('INSERT INTO RELATIONS (C_ID, M_ID, A_ID, A_INDEX)');
Query.SQL.Add('SELECT c.C_ID, 0, a.A_ID,:A_INDEX');
Query.SQL.Add('FROM CATEGORIES c, ACTIONS a');
Query.SQL.Add('WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION');
Query.SQL.EndUpdate;
Query.Params.CreateParam(TFieldType.ftInteger, 'A_INDEX', ptInput);
Query.Params.CreateParam(TFieldType.ftFixedWideChar, 'CATEGORY', ptInput);
Query.Params.CreateParam(TFieldType.ftFixedWideChar, 'ACTION', ptInput);
Query.ParamByName('CATEGORY').Size := 255;
Query.ParamByName('ACTION').Size := 255;
Query.Prepare;
Query.ParamByName('A_INDEX').Value := 0;
Query.ParamByName('CATEGORY').Value := 'Foo';
Query.ParamByName('ACTION').Value := 'Foo';
Query.ExecSQL; // <-- Exception
finally
Query.Free;
end;
end;
我还在学习SQL,数据库和FireDAC所以我真的不明白为什么它允许我在select语句中输入一个直接值但是param是不行的。
如何使用第一个查询动态地将参数插入A_INDEX
列?
答案 0 :(得分:1)
您不能像这样参数化查询:
INSERT INTO RELATIONS (C_ID, M_ID, A_ID, A_INDEX)
SELECT c.C_ID, 0, a.A_ID, :A_INDEX
FROM CATEGORIES c, ACTIONS a
WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION
特别是 SELECT 表达式:
SELECT c.C_ID, 0, a.A_ID, :A_INDEX
您可以克服这种情况的唯一方法是预处理器宏,但它们在修改SQL命令时不能作为真正的查询参数工作,因此DBMS必须再次准备命令。
例如:
procedure Test;
var
Query: TFDQuery;
begin
Query := TFDQuery.Create(nil);
try
Query.Connection := DBDataModule.dbMain;
Query.SQL.Add('INSERT INTO RELATIONS (C_ID, M_ID, A_ID, A_INDEX)');
Query.SQL.Add('SELECT c.C_ID, 0, a.A_ID, &A_INDEX'); // ← & defines macro
Query.SQL.Add('FROM CATEGORIES c, ACTIONS a');
Query.SQL.Add('WHERE c.NAME = :CATEGORY AND a.NAME = :ACTION');
Query.ParamByName('CATEGORY').Value := 'Foo';
Query.ParamByName('ACTION').Value := 'Foo';
Query.MacroByName('A_INDEX').AsIdentifier := '0';
Query.ExecSQL;
finally
Query.Free;
end;
end;
但是如果 A_INDEX 字段值应该是自动增量值,请像这样创建它。或者,如果它是来自另一个表的值,则在查询中加入该表。宏不能作为真正的命令参数工作,并且在插入许多期望准备好的命令的记录时可能效率低下。
答案 1 :(得分:0)
您可能在DFM中设置了SQL(直接在组件中),您可以在组件的Params属性中看到创建的参数。删除所有参数或手动添加A_INDEX(整数,输入)。
我强烈建议您在源代码中创建params,并将属性ParamCreate设为false。如果您知道需要手动创建,则可以轻松控制它。
要手动创建参数,请使用CreateParam方法(在TParams类中)。