我正在对SQL Server 2008 R2数据库运行MERGE
语句(在2008兼容模式下)
确切的合并语句SQL是不相关的,但这里有一个合并语句的例子:
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执行此语句时,它执行正确。
但是当我的软件在客户端PC上运行时,Windows XP或Windows Server 2003 R2, sql CommandText
在到达服务器之前被更改。在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在微软论坛上报告了同样的问题:
SQL MERGE语法适用于Win7 SP1客户端,但不适用于早期平台
我相信ADO在将SQL发送到服务器之前会解析SQL。在Win7 SP1和WinServer 2008 R2中更新了数据访问组件。然而,我相信XP SP3的数据访问组件早于SQL Server 2008。
这就是为什么SQL可以在Win7 SP1中工作而不能在XP中工作。
我的'解决方案'是将SQL封装在
EXEC
中,以便ADO允许它通过,如:EXEC(合并等。)
他的hack确实有效,更改:
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和底层提供者将文本视为原始。
目前修复hack是:
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 ...
由于没有解决方案,并且ADO(虽然不是死亡)已经完成,因此破解是的答案。
永远不要在没有注释行的情况下发出MERGE
语句:
--Dummy leading comment line to thwart ADO from mangling MERGE on Windows XP/2003R2
MERGE Users
USING (VALUES ...