将查询的值获取到参数中

时间:2012-11-28 12:50:58

标签: sql sql-server delphi

我正在尝试将我们在项目中使用的一些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行的查询中选择正确的参数值?

2 个答案:

答案 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;