【发布时间】:2016-12-12 09:31:35
【问题描述】:
这个问题是 Microsoft ODBC 中一系列错误的一部分 司机:
- ODBC driver fails to raise errors; but instead suppresses them
- Reading columns out of order returns incorrect results
- Cannot execute a stored procedure that is a SYNONYM
微软已经表示他们不会在他们的 ODBC 中修复这些错误 司机。
背景
如果我有一个示例表:
CREATE TABLE Wallet (
WalletID int NOT NULL,
Name varchar(50) NOT NULL
)
我尝试发出插入到表中的 sql,但没有为 NOT NULL WalletID 列指定值:
INSERT INTO Wallet (WalletID, Name) VALUES (1, 'Fan')
INSERT INTO Wallet (Name) VALUES ('Ardent Defender') --Constraint violation
SQL Server 报错:
(1 行受影响)
消息 515,第 16 级,状态 2,第 2 行
无法将值 NULL 插入列“WalletID”、表“Scratch.dbo.Wallet”;列不允许空值。插入失败。
该语句已终止。
这是有道理的。
使用 ADO/OLEDB 和 SQL Server OLE DB 提供程序 (SQLOLEDB) 连接时:
Provider=SQLOLEDB;Data Source=hyperion;User ID=Contoso;Password=Trub4dor;
并且我执行了INSERT,ADO/OLEDB/COM 基础结构返回一个失败,作为异常返回到高级语言:
无法将值 NULL 插入到列 'WalletID'、表 'Wallet' 中;列不允许空值。插入失败
这一切都说得通。
但请尝试使用 ODBC 驱动程序
由于 本机客户端 OLE DB 提供程序(和the MS recommendation that you do not use the native client ODBC drivers)的贬低,我想我会尝试使用 SQL Server ODBC 驱动程序:
Provider=MSDASQL;Driver={SQL Server};Server={hyperion};UID={Contoso};PWD={Trub4dor};
更新 - 不推荐使用:六年后,Microsoft 有了announced the un-deprecation of OLE DB support for SQL Server,并为 SQL Server 创建了第三个 OLE DB 驱动程序:msoledbsql。 (archive)
以前,Microsoft announced deprecation of the Microsoft OLE DB Provider for SQL Server,是 SQL Server Native Client (SNAC) 的一部分。当时,我们做出这个决定是为了在我们使用 Azure SQL 数据库进入云时代时,尝试为围绕 Windows 原生软件开发的开发人员故事提供更多的简单性,并尝试为开发人员利用 JDBC 和 ODBC 的相似性。然而,在随后的审查中,确定弃用是一个错误,因为 SQL Server 中的大量场景仍然依赖于 OLE DB,并且更改这些场景会破坏一些现有的客户场景。
考虑到这一点,我们决定弃用 OLE DB,并在
2018 日历年第一季度2018 年 3 月之前发布新版本。
我发出我的批次:
INSERT INTO Wallet (WalletID, Name) VALUES (1, 'Fan')
INSERT INTO Wallet (Name) VALUES ('Ardent Defender')
我惊讶地发现同样的 SQL 语句:
在使用 ODBC 驱动程序时会静默失败。该语句执行时不会引发任何错误。
当我的 SQL 语句运行没有错误时,我困惑了大约一个小时,但是这些行不会出现在数据库中。
静默失败
显然,无声的失败是不好的。
但是发生了什么?
我如何告诉 ADO-OLEDB-ODBC 驱动程序报告错误。它是 ODBC 连接字符串设置吗?是 MSDASQL 连接字符串设置吗?
示例伪代码
我实际上将 Delphi 与 ADO 一起使用。但我会将其转码为伪 C# 样式代码,以便于概念理解。
String commandText =
"INSERT INTO Wallet (WalletID, Name) VALUES (1, 'Fan')"+CRLF+
"INSERT INTO Wallet (Name) VALUES ('Ardent Defender')";
ADOConnection conn = new ADOConnection();
conn.ConnectionString = szConnectionString;
conn.Open();
HRESULT hr = conn.Execute(commandText, ref recordsAffected, [eoExecuteNoRecords]);
实际上,HRESULT 的检查是由语言基础结构和编译器魔法处理的 - 如果 FAILED 会引发本地语言异常。
【问题讨论】:
-
是你没有设置接收错误信息的命令的问题吗?
-
可以贴一下应用代码sn-p吗?我无法复制。
-
请显示一些最小代码。我有测试用例明确测试这样的失败,一切都按预期工作(使用 sql server 2014 和本机客户端驱动程序,在 windows 上使用 c++)。
-
@erg 找出了重要的部分:它必须是批处理中的多个语句,随后的语句失败。
-
@DanGuzman 我发现了使人为测试失败的缺失技巧:第一个语句不会失败的多个语句。
标签: sql-server sql-server-2008-r2 odbc oledb ado