2013-06-11 1 views
1

Я запускаю инструкцию MERGE к базе данных SQL Server 2008 R2 (которая находится в режиме совместимости 2008 года).Как предотвратить изменение ADO моего текста команды SQL?

Точное слияния оператор 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, он правильно выполняет.

Но когда мое программное обеспечение работает на клиентском ПК под управлением 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 пытаясь выполнить его против базы данных SQL Server 2008 R2.

Питер бултон сообщил один и тот же вопрос на форумах Microsoft:

SQL MERGE syntax works with Win7 SP1 client but fails with earlier platforms

I believe ADO parses the SQL before it sends it to the server. The data access components were updated for Win7 SP1 and also WinServer 2008 R2. However, I believe XP SP3's data access components predate SQL Server 2008.

That's why the SQL works from Win7 SP1 but not from XP.

My 'solution' was to wrap the SQL in an EXEC so that ADO allows it through, as in:

EXEC('MERGE....etc.')

Его хак, конечно, работает, изменение:

MERGE Users ... 

в

EXEC('MERGE Users' ...) 

, но я хотел бы придумать реальное решение. Я не знаю, кто в цепочке несет ответственность за изменение текста моей команды:

ADO -> OLEDB -> SQLOLEDB -> SQL Server

но я хочу, чтобы они остановились.

Как я, через ADO, указать свой текст команды и SQLOLEDB не изменить его?

Сейчас мой код :

String sqlCommandText = "MERGE Users" //snip; 
int recordsAffected; 

connection.Execute(
    sqlCommandText, 
    out recordsAffected, 
    adCmdText | adExecuteNoRecords); 

я не вижу ExecuteOptionEnum или CommandTypeEnum сказать ADO, и лежащие в основе поставщиков, чтобы рассматривать текст, как сырой.


В настоящее время Fixup хак:

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

Update: Лучше обходной путь взломать

Вместо того, чтобы упаковка целиком заявление в EXEC(...), я нашел более безопасный трюк, чтобы победить ADO, чтобы предшествовать заявлению с помощью комментарий.Даже пустой комментарий будет делать:

-- 
MERGE Users 
USING (VALUES ... 

В действительности вы будете хотеть иметь некоторый текст, объясняющий, что комментарий пустая строка критически к не делает работу запроса:

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

ответ

2

Поскольку нет раствор и ADO (в то время как не dead) сделан, hack есть ответ.

Никогда не выдавать MERGE заявления без ведущей строки комментария:

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

Кроме заявления, начиная с «с» для КТР функция также влияет! –

+0

@ BerndOtt Это хорошая записка; и ужасающая реальность. Теперь я должен пройти еще один раунд обзора всего кода повсюду. :( –