0

我正在尝试将我们在项目中使用的一些 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 行的查询可以直接选择参数值时,是否有办法?

4

2 回答 2

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 微小的 int 字段,因此字段值也可能会返回0。但是您不会在发布的代码中使用此值。

于 2012-11-28T13:42:51.317 回答
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;
于 2012-11-28T13:16:41.407 回答