如何防止ADO更改我的SQL命令文本?

时间:2013-06-11 19:07:58

标签: sql-server-2008 merge windows-xp adodb sqloledb

我正在针对SQL Server 2008 R2数据库(处于2008兼容模式)运行MERGE语句。

确切的合并语句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上运行时,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 syntax works with Win7 SP1 client but fails with earlier platforms

     

我相信ADO会在将SQL发送到服务器之前对其进行解析。针对Win7 SP1和WinServer 2008 R2更新了数据访问组件。但是,我相信XP SP3的数据访问组件早于SQL Server 2008。

     

这就是为什么SQL可以从Win7 SP1运行而不是从XP运行。

     

我的'解决方案'是将SQL包装在EXEC中,以便ADO允许它通过,如:

     

EXEC( 'MERGE ....等。')

他的黑客当然有效,改变:

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);

我没有看到任何ExecuteOptionEnumCommandTypeEnum告诉ADO和基础提供商将文本视为 raw


目前修正黑客是:

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 ...

1 个答案:

答案 0 :(得分:2)

由于没有解决方案,并且ADO(虽然不是)已完成,黑客 答案。

在没有前导评论专栏的情况下,永远不要发出MERGE语句:

--Dummy leading comment line to thwart ADO from mangling MERGE on Windows XP/2003R2
MERGE Users
USING (VALUES ...