在某些情况下,ADO 组件,尤其是 TADOCommand,是不是可以更可靠地使用未命名或命名参数?
Posted
技术标签:
【中文标题】在某些情况下,ADO 组件,尤其是 TADOCommand,是不是可以更可靠地使用未命名或命名参数?【英文标题】:Do ADO components, especially TADOCommand, work more reliably with un-named, or named parameters, in some cases?在某些情况下,ADO 组件,尤其是 TADOCommand,是否可以更可靠地使用未命名或命名参数? 【发布时间】:2012-06-17 13:27:34 【问题描述】:*** 上的几个问题似乎在 ADO/OleDB、delphi TADOQuery/TADOCommand 和参数主题上的答案相互矛盾。
可以通过两种方式引入参数,在 ADO 组件的 CommandText 或 SQL 属性中。对我来说大部分时间都有效的命名参数是用冒号介绍的:
select a, b, c from bar where bat = :baz
这对我来说 99% 的时间都有效。我时不时地发现 ADO 或 Delphi 的包装器不接受 ":baz" 并要求我改写这个:
select f, g, h from bar where bat = ?
这会产生一个未命名的参数,而不是一个命名的参数。当 ADO 查询或 ADO 命令只包含一个参数时,这没什么大不了的。但那不是 ADO 对我起作用的时候。昨天它以一种方式运行,而今天,在一个 TADOCommand 对象中使用双命令的另一种方式,就像这样,在一个 CommandText 字符串中使用两个命令:
delete from bar where id = :id1
delete from bat where id = :id2
我不得不把它改成这样:
delete from bar where id = ?
delete from bat where id = ?
昨天一整天都在工作。今天,我不得不把它改回第一个版本,让它工作。症状是 ADO 参数消失了,再也回不来了,当我尝试执行命令时出现错误,索引超出范围,当我尝试访问 Parameters[0]
时。没有给我任何关于参数正在消失的警告。似乎在设计时与 ADO 数据集的一些连接特别是在运行 TADOCommand
组件,并且它“只是让我失望”。当您尝试编写查询或命令时尤其令人抓狂,并且您知道它有效,但 ADO 组件已决定不接受“?”或“:x”现在。您可以通过从一个切换到另一个来解决它完全无法运行的问题。但这让我感到沮丧,并且可能实际上完全阻止了其他人。我知道有些人总是在代码中动态构建他们的 SQL,并避免使用Parameters
,也许这就是原因。
我预期的问题的可能答案是:
ADO 不支持多个命令,或者至少 Delphi 的包装器不支持。或者 TADOCommand
在这里不能可靠地工作。
参数是所有 ADO 或所有 Delphi 的 ADO 包装器中的错误区域?
你做错了。
我使用的是 Delphi XE2,但我在 2007、2009、2010 和 XE 中看到了类似的狡猾行为。 我正在使用 Microsoft OLEDB Provider for SQL Server 作为我的 OLEDB Provider。
【问题讨论】:
如果你用分号(对于 SQL Server)分隔这两个命令会有什么不同吗? 在不需要数据感知控件的项目中,我有时会直接使用 ADODB 和 ADOInt。像这里:xxm.svn.sourceforge.net/viewvc/xxm/trunk/Delphi/demo2/03%20Data/…我还没有检查这对性能有什么影响,但真的应该检查这些日子之一(并将我的结果发布在这里作为答案)...... SilentD:我会试试分号。我记得 Delphi ado 组件也不能很好地支持分隔符。 了解 Delphi 版本会很有趣,因为我记得 Delphi 7.1 中有一些非常丑陋的错误。并不是说它们现在都消失了,但它可能会降低风险。在谈论参数时,您是否尝试清除语句,调用 Prepare (iirc)。您是否尝试改用 TADOQuery 或 TADODataSet? 这有什么关系?项目组不会更改 DFM 表单上 ADO 组件的行为。 【参考方案1】:使用:
命名的参数?我总是将它与@
一起使用,即使在 Visual Studio (ADO.NET) 上也是如此。
并且在 T-SQL 中参数和变量都以@
为前缀。
不记得有问题...你确定你没有选择 Native Client (与 SQL Server 客户端一起安装)而不是用于 SQL Server 的 OLEDB 提供程序(其中 Windows 自带)?
【讨论】:
【参考方案2】:不幸的是,我有一段时间没有使用 Delphi,所以,我没有办法从 Delphi 的角度验证这个答案。
这是我第一次看到以冒号 (:
) 为前缀的命名参数。通常,在 ADODB 中,命名参数以 at (@
) 为前缀,是的,未命名参数以问号 (?
) 给出。
命名参数的一个显着优势是它们能够被重用,即
INSERT INTO TABLE T VALUES (@id, @id, 'Hello World');
在 ADODB 级别。一旦您使用了参数,无论是命名的还是未命名的,您都可以使用CommandText.Parameters.Refresh
作为创建参数的快速方法。
【讨论】:
"通常,在 ADODB 中,命名参数以 at (@) 为前缀" -- ADODB 没有命名参数,除了存储过程的参数,除非您有一个特殊的提供程序增加了对他们的支持。至少,常用的 SQLOLEDB 提供程序没有它们。在 ADO.NET 中,可以使用您提到的 @ 前缀命名参数,但在 Delphi 中不能轻松使用 ADO.NET。【参考方案3】:是的,在某些情况下?
的参数会失败。我发现有时我需要使用:named
参数。命名参数对于使用 DB Parameter 值具有优势,因为设置 Name 属性也可以更轻松地调试 ADO 查询或数据集或表。
我不明白为什么。如果您遇到此问题,请首先检查您使用的是正确的 OLEDB 提供程序,并检查是什么版本。还要检查由您生成的错误 SQL 导致的潜在解析错误。
我怀疑 OLEDB 提供程序内部的代码中我没有源代码的内部行为是这个怪癖的罪魁祸首。 Delphi ADO 类包装器是从 Delphi 的数据库组件层架构到 ADO 的核心查询/表/数据集 API 的转换器,所有这些 API 都是围绕一组处理 ADO RecordSets 的 COM 对象的底层包装器。
【讨论】:
以上是关于在某些情况下,ADO 组件,尤其是 TADOCommand,是不是可以更可靠地使用未命名或命名参数?的主要内容,如果未能解决你的问题,请参考以下文章
如何将自定义子查询传递给 ADO.NET 中的 SQL 命令?
可以从 sql server 中的 sproc 返回到 ADO.NET 应用程序的最大数据量是多少
在没有记录集循环的情况下使用 ado 和 vbscript 从 csv 更新数据库?
在不访问 SQL Server Profiler 的情况下分析 ADO.NET 语句
哪位高手简洁分析下ADO.NET中的常用对象:DataAdapter、Command、DataSet的使用情况。。非常感谢!!