【问题标题】:Assignment error when assign value to parameter of a parametized query为参数化查询的参数赋值时出现赋值错误
【发布时间】:2012-08-18 20:02:19
【问题描述】:

我正在使用带有 AnyDac 组件和 Advantage Database 10 的 Delphi XE2。 在我的代码中,我使用这样的参数化查询:

q.SQL.Text := 'SELECT * FROM Table1 ' +
  'LEFT JOIN Table2 ON (Table1.ID = Table1 .ID_Table2) ' +
  'WHERE ' +
  ':0 BETWEEN Table1.StartAm AND Table1.EndeAm ' +
  'AND Table2 = :1';
q.Params[0].Value := AStartDateTime;
q.Params[1].Value := AIDRessourcenGruppe;
q.Open;

这会导致异常:

异常 der Klasse EADSNativeException mit der Meldung '[AnyDAC][Phys][ADS] 错误 7200:AQE 错误:状态 = 22018;
本机错误 = 2112; [iAnywhere 解决方案][优势 SQL Engine]Assignment error' aufgetreten.

当然 AStartDateTime 是一个有效的 delphi TDateTime 值,AIDRessourcenGruppe 是一个整数值。

有趣的是,这两种变体都有效:

q.SQL.Text := 'SELECT * FROM Table1 ' +
  'LEFT JOIN Table2 ON (Table1.ID = Table1 .ID_Table2) ' +
  'WHERE ' +
  ':0 BETWEEN Table1.StartAm AND Table1.EndeAm ' +
  'AND Table2 = :1';
q.Params[0].AsDateTime:= AStartDateTime;
q.Params[1].AsInteger:= AIDRessourcenGruppe;
q.Open;

-

q.SQL.Text := 'SELECT * FROM Table1 ' +
  'LEFT JOIN Table2 ON (Table1.ID = Table1 .ID_Table2) ' +
  'WHERE ' +
  ':SomeDate BETWEEN Table1.StartAm AND Table1.EndeAm ' +
  'AND Table2 = :ID_PT_Ressourcengruppe';
q.ParamByName('SomeDate').Value := AStartDateTime;
q.ParamByName('ID_PT_Ressourcengruppe').Value := AIDRessourcenGruppe;
q.Open;

我错过了什么吗?感谢您的帮助!

【问题讨论】:

  • 那么为什么不使用AsType 转换呢?它的可读性更好,您可以确定查询参数构建器的内部机制将正确处理这些值。我不知道 AnyDAC,但是如果他们从 Delphi 那里得到这个,那么 Value 的类型是 Variant 在我看来不会给你带来任何安全......
  • 努力+1 但q 来自哪里?你的最后一个变体使用dm1.qCustom,你的另外两个使用qq 是如何声明的?您能否向我们展示这两个参数的声明。当您说它是有效的日期时间时,据我们所知,AStartDateTime 被声明为字符串,其值为“01-01-2012”。为什么将 :0 作为参数更改为 :SomeDate
  • 对那个 dm1.qCustom 感到抱歉 - 我将它替换为 'q' 只是为了缩短代码-sn-p 并忘记了一些...AStartDate 被声明为 TDateTime,而不是字符串。我将 :0 更改为 :SomeDate 只是为了显示命名参数的使用。
  • 是的,它没有解释为什么。无论如何,Delphi 不负责确定正确的数据类型,也不知道如何将通过 Variant 类型传递的日期时间戳转换为查询。对参数的索引访问也可能发生同样的情况,因为我认为它不会在内部确定参数的数据类型,而命名访问却可以。而且,在这种情况下,我看不到任何使用Value 的专业人士,使用索引方式是(因为它更快),但在Variant 之前使用直接AsType 类型转换总是对我有利(你不能不匹配参数) .
  • .AsDateTime 是快速代码,.Value 是惰性代码 :-)

标签: delphi parameters delphi-xe2 advantage-database-server anydac


【解决方案1】:

答案 - 只是猜测:

我会说对参数的Value 属性的索引写入访问不能确定参数的数据类型,而命名访问却可以。如果这是正确的,那么您就有麻烦了,因为您通过 Variant 类型传递所有值,在执行查询之前必须将其转换为正确的值格式。但这一切只是我的猜测——我根本不知道 AnyDAC!

AsType 值访问:

我发布这个只是因为我不喜欢 Value 访问被称为专业的参数 :-)
最好使用AsType 类型转换,至少因为:

  • 更快,因为你直接说出你要传递给某个参数的类型,因此查询参数引擎不需要确定这一点,并且与Value访问相比,它不需要需要转换Variant类型

  • 这对你来说更安全,因为你不能通过例如字符串值到AsDateTime 访问的参数,所以你有一个额外的保护,防止参数不匹配

我在你的例子中推荐的是使用索引访问参数,而不是常用的命名,它需要在访问之前搜索参数列表并且速度较慢。

【讨论】:

  • 嘿 TLama,感谢您的回答。我经常在 devExpress 和其他组件的代码中看到对 .value 属性的访问。所以我的想法是使用它必须是安全的;)回到问题:它似乎没有真正的原因为什么它不起作用,所以最好联系 AnyDAC 支持 - 我想知道那里出了什么问题..
  • @user1619275 是有原因的。正如我之前写的 - 你使用不同对象的方法。为什么你坚持认为不同的对象工作完全一样?比较 q.Params.Items[i]q.Params.ParamByName('...'),而不是 q.ParamByName('... ')
  • @Arioch'The:请不要再重复了,因为这是错误的。打开 IDE,建立数据库连接,然后自己进行测试。此外,您不必对这里的每一篇文章都进行大讨论 - 这不是聊天室。
  • 这是我的第一个猜测。变体通常是“邪恶的”,因为它们仅通过猜测数据类型是什么来进行幕后转换。由于 DateTime 通常表示为浮点值,因此这里的猜测很容易出错。
  • +1。在我的书中,任何避免使用变体开销的方法都更好。
猜你喜欢
  • 2018-06-19
  • 1970-01-01
  • 2012-03-18
  • 1970-01-01
  • 2013-04-17
  • 2014-09-21
  • 1970-01-01
  • 2014-02-14
  • 1970-01-01
相关资源
最近更新 更多