我正在MERGE
针对 SQL Server 2008 R2 数据库(处于 2008 兼容模式)运行语句。
确切的合并语句 SQL 无关紧要,但这里是 MERGE 语句的示例:
MERGE Users
USING (VALUES
('{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}')
) AS rows(UserGUID)
ON Users.UserName = rows.UserName
WHEN NOT MATCHED BY SOURCE THEN
DELETE; --always end MERGE with semi-colon
从 SSMS 或运行 Windows 7 的客户端 PC 执行此语句时,它会正确执行。
但是,当我的软件在 Windows XP 或 Windows Server 2003 R2 的客户端 PC 上运行时,sqlCommandText
在到达服务器之前被更改。在 SQL Server Profiler 中,我可以看到正在执行的 SQL 是:
exec MERGE Users
USING (VALUES
('{77410DC5-7A3E-4F1A-82C6-8EFB3068DE66}')
) AS rows(UserGUID)
ON Users.UserName = rows.UserName
WHEN NOT MATCHED BY SOURCE THEN
DELETE; --always end MERGE with semi-colon
哪个不是有效的 SQL,SQL Server 会抛出错误:
Incorrect syntax near the keyword 'MERGE'
您可以通过尝试对 SQL Server 2008 R2 数据库执行它来确认它是无效的 SQL。
Peter Boulton 在 Microsoft 论坛上报告了同样的问题:
SQL MERGE 语法适用于 Win7 SP1 客户端,但在早期平台上失败
我相信 ADO 在将 SQL 发送到服务器之前会对其进行解析。针对 Win7 SP1 和 WinServer 2008 R2 更新了数据访问组件。但是,我相信 XP SP3 的数据访问组件早于 SQL Server 2008。
这就是 SQL 在 Win7 SP1 上工作但在 XP 上不行的原因。
我的“解决方案”是将 SQL 包装在一个中,
EXEC
以便 ADO 允许它通过,如下所示:EXEC('合并....等')
他的技巧当然有效,改变:
MERGE Users ...
进入
EXEC('MERGE Users' ...)
但我想提出真正的解决方案。我不知道链中的谁负责更改我的命令文本:
ADO -> OLEDB -> SQLOLEDB -> SQL Server
但我希望他们停下来。
我如何通过 ADO 指定我的命令文本,并且让 SQLOLEDB 不修改它?
现在我的代码是1:
String sqlCommandText = "MERGE Users" //snip;
int recordsAffected;
connection.Execute(
sqlCommandText,
out recordsAffected,
adCmdText | adExecuteNoRecords);
我没有看到任何ExecuteOptionEnum
,或者CommandTypeEnum
告诉 ADO 和底层提供者,将文本视为原始的。
现在修复黑客是:
sql = "MERGE Users" ...
ExecuteNoRecords(connection, sql);
使用修改后的助手:
int ExecuteNoRecords(Connection connection, String sql)
{
//20130611: Fix bug in ADO that mangles/breaks SQL it doesn't understand (e.g. MERGE on Windows XP)
String obfuscatedCommandText = 'EXEC(' + QuotedStr(sql)+ ')';
int recordsAffected;
connection.Execute(obfuscatedCommandText, out recordsAffected, adCmdText | adExecuteNoRecords);
return recordsAffected;
}
更新:更好的解决方法黑客
与其将整个语句包装在 中EXEC(...)
,我发现击败 ADO 的一个更安全的技巧是在语句之前加上注释。即使是空的评论也可以:
--
MERGE Users
USING (VALUES ...
实际上,您需要一些文本来解释空注释行对于使查询正常工作至关重要:
--Leading comment to thwart ADO from mangling MERGE on Windows XP/2003R2
MERGE Users
USING (VALUES ...