我正在尝试将我们在项目中使用的一些SQL代码转换为使用参数。插入工作正常:
with SQLDataSet do begin
Close;
SQL.Text := 'INSERT INTO testtable (keyname, waarde) VALUES (:keyname,:waarde)';
Prepare;
for i := 1 to 10000 do begin
ParamByName('waarde').AsInteger := i;
ParamByName('keyname').AsString := 'Testa'+IntToStr(i);
ExecSql;
end;
end;
工作正常而且快速。
但是,我不能让它与选择语句一起使用。 起初以下似乎有效:
with SQLDataSet do begin
SQL.Clear;
SQL.Text := 'SELECT :waarde = waarde FROM testtable WHERE keyname = :keyname';
Prepare;
for i := 1 to 10000 do begin
ParamByName('keyname').AsString := 'Testa'+IntToStr(i);
ExecSQL;
k[i] := ParamByName('waarde').AsInteger;
Close;
end;
end;
但是k [i]的值只是填充了0。我是否需要继续选择旧式方式,发出查询,打开和遍历结果集,还是有一种方法可以在只有1行的查询中选择正确的参数值?
答案 0 :(得分:2)
简答:按照现在的方式继续这样做。没有理由使用参数来获取查询结果。
更长的回答:
您可以使用ADOCommand(不确定ODBCExpess等价物是什么)并执行SELECT INTO
查询:
SELECT
YourField
INTO
:YourParam
FROM
YourTable
WHERE
ID = 1
以类似的方式执行存储过程。
但是,使用参数主要是为了确保输入有效并被视为某种类型。它还允许数据库使用更好的缓存,因为它们缓存查询一次并将参数视为可变块。
对于输出(返回的字段),这是没用的。即使使用普通列,查询也已缓存。因此,只需执行查询并像现在一样读取其字段。您可以使用参数,但它们只会增加更多的复杂性和限制,而不会带来任何好处。这些参数对于读取存储过程和程序块的输出特别有用。
在你的特定情况下,你想要检索很多字段(可能都是?)在这种情况下,执行单个查询并循环遍历结果可能比执行现有的1000个小查询更好。每个查询都有一些初始化等开销,如果您设法一次查询所需的所有数据,则可以节省1000倍的开销。 此外,如果您这样做(获取多个数据记录),则无法将这些结果提取到参数中,因此这是参数限制您的原因之一,因此如果可以的话,仅将参数用于输入的另一个原因。
您的结果:
您获得0
的原因是您从未设置参数值。所以它的值仍为NULL。因为您使用AsInteger
请求值,所以此值将转换为整数,因此返回0
。
查询返回的值(返回的一个字段)也可能是0
。实际上,您查询表达式X = Y
,其中X是参数的值,Y是字段的值。由于参数的值为NULL,因此表达式始终计算为false(使用NULL值上的常规比较运算符始终返回false,无论您使用哪个运算符或其他值是什么)。由于true和false通常表示为0/1 tiny int字段,因此字段值也可能返回0
。但是,您不要在发布的代码中使用此值。
答案 1 :(得分:1)
您无法参数化列名称。 waarde必须是表中的列名。您应该将代码更改为这样的代码。 (未经测试)
with SQLDataSet do begin
SQL.Clear;
SQL.Text := 'SELECT waarde FROM testtable WHERE keyname = :keyname';
Prepare;
for i := 1 to 10000 do begin
ParamByName('keyname').AsString := 'Testa'+IntToStr(i);
ExecSQL;
k[i] := SQLDataSet['waarde'];
Close;
end;
end;