我有一个客户 ODBC 应用程序,可以对大多数操作后受影响的行进行完整性检查。突然之间,这些检查都失败了。在这种情况下,插入后受影响的行预计为 1。查看日志后,该值返回未知 (-1)。
有谁知道为什么行为会改变?
附加信息:
- 应用程序在 Windows 服务器上运行
- 数据库是甲骨文。
- 驱动程序是 Microsoft Oracle 驱动程序
- 客户表示最近没有升级数据库或驱动程序。
- 客户声称问题是在更改/删除表中的几行后开始的。
额外细节:
驱动程序为“Microsoft ODBC for Oracle”,版本为 2.576.3959.00,文件名为 MSORCL32.dll,日期为 2/17/2007。Oracle 数据库级别为 10.2。
有任何想法吗?
这是我让他们捕获的 ODBC 日志:
dpxag35 a5c-cac ENTER SQLExecDirect HSTMT 015A2270 UCHAR * 0x00177D9C [ 364] "begin \ a <single simple insert statement here>; \ aend;" SDWORD 364 dpxag35 a5c-cac EXIT SQLExecDirect with return code 0 (SQL_SUCCESS) HSTMT 015A2270 UCHAR * 0x00177D9C [ 364] "begin \ a <single simple insert statement here>; \ aend;" SDWORD 364 dpxag35 a5c-cac ENTER SQLNumResultCols HSTMT 015A2270 SWORD * 0x0012F9B0 dpxag35 a5c-cac EXIT SQLNumResultCols with return code 0 (SQL_SUCCESS) HSTMT 015A2270 SWORD * 0x0012F9B0 (0) dpxag35 a5c-cac ENTER SQLRowCount HSTMT 015A2270 SQLLEN * 0x00163B88 dpxag35 a5c-cac EXIT SQLRowCount with return code 0 (SQL_SUCCESS) HSTMT 015A2270 SQLLEN * 0x00163B88 (-1) dpxag35 a5c-cac ENTER SQLFreeStmt HSTMT 015A2270 UWORD 0 <SQL_CLOSE> dpxag35 a5c-cac EXIT SQLFreeStmt with return code 0 (SQL_SUCCESS) HSTMT 015A2270 UWORD 0 <SQL_CLOSE>
作为参考,这是来自 MSDN 上的 ODBC 文档:
行计数点[输出] 指向要在其中返回行数的缓冲区。对于 UPDATE、INSERT 和 DELETE 语句,对于 SQLBulkOperations 中的 SQL_ADD、SQL_UPDATE_BY_BOOKMARK 和 SQL_DELETE_BY_BOOKMARK 操作,以及对于 SQLSetPos 中的 SQL_UPDATE 或 SQL_DELETE 操作,*RowCountPtr 中返回的值是受请求影响的行数或 –1如果受影响的行数不可用。在调用 SQLExecute、SQLExecDirect、SQLBulkOperations、SQLSetPos 或 SQLMoreResults 时,将诊断数据结构的 SQL_DIAG_ROW_COUNT 字段设置为行数,并以与实现相关的方式缓存行数。SQLRowCount 返回缓存的行计数值。缓存的行计数值在语句句柄设置回准备或分配状态之前有效,语句被重新执行,或者 SQLCloseCursor 被调用。请注意,如果在设置 SQL_DIAG_ROW_COUNT 字段后调用了函数,则 SQLRowCount 返回的值可能与 SQL_DIAG_ROW_COUNT 字段中的值不同,因为 SQL_DIAG_ROW_COUNT 字段被任何函数调用重置为 0。对于其他语句和函数,驱动程序可以定义在 *RowCountPtr 中返回的值。例如,某些数据源可能能够在获取行之前返回由 SELECT 语句或目录函数返回的行数。注意 许多数据源在获取结果集之前无法返回结果集中的行数;为了获得最大的互操作性,应用程序不应依赖此行为。请注意,如果在设置 SQL_DIAG_ROW_COUNT 字段后调用了函数,则 SQLRowCount 返回的值可能与 SQL_DIAG_ROW_COUNT 字段中的值不同,因为 SQL_DIAG_ROW_COUNT 字段被任何函数调用重置为 0。对于其他语句和函数,驱动程序可以定义在 *RowCountPtr 中返回的值。例如,某些数据源可能能够在获取行之前返回由 SELECT 语句或目录函数返回的行数。注意 许多数据源在获取结果集之前无法返回结果集中的行数;为了获得最大的互操作性,应用程序不应依赖此行为。请注意,如果在设置 SQL_DIAG_ROW_COUNT 字段后调用了函数,则 SQLRowCount 返回的值可能与 SQL_DIAG_ROW_COUNT 字段中的值不同,因为 SQL_DIAG_ROW_COUNT 字段被任何函数调用重置为 0。对于其他语句和函数,驱动程序可以定义在 *RowCountPtr 中返回的值。例如,某些数据源可能能够在获取行之前返回由 SELECT 语句或目录函数返回的行数。注意 许多数据源在获取结果集之前无法返回结果集中的行数;为了获得最大的互操作性,应用程序不应依赖此行为。SQLRowCount 返回的值可能与 SQL_DIAG_ROW_COUNT 字段中的值不同,因为 SQL_DIAG_ROW_COUNT 字段被任何函数调用重置为 0。对于其他语句和函数,驱动程序可以定义在 *RowCountPtr 中返回的值。例如,某些数据源可能能够在获取行之前返回由 SELECT 语句或目录函数返回的行数。注意 许多数据源在获取结果集之前无法返回结果集中的行数;为了获得最大的互操作性,应用程序不应依赖此行为。SQLRowCount 返回的值可能与 SQL_DIAG_ROW_COUNT 字段中的值不同,因为 SQL_DIAG_ROW_COUNT 字段被任何函数调用重置为 0。对于其他语句和函数,驱动程序可以定义在 *RowCountPtr 中返回的值。例如,某些数据源可能能够在获取行之前返回由 SELECT 语句或目录函数返回的行数。注意 许多数据源在获取结果集之前无法返回结果集中的行数;为了获得最大的互操作性,应用程序不应依赖此行为。某些数据源可能能够在获取行之前返回由 SELECT 语句或目录函数返回的行数。注意 许多数据源在获取结果集之前无法返回结果集中的行数;为了获得最大的互操作性,应用程序不应依赖此行为。某些数据源可能能够在获取行之前返回由 SELECT 语句或目录函数返回的行数。注意 许多数据源在获取结果集之前无法返回结果集中的行数;为了获得最大的互操作性,应用程序不应依赖此行为。
在 doco 页面的最后,我们得到了这个:
如果在语句句柄上执行的最后一个 SQL 语句不是 UPDATE、INSERT 或 DELETE 语句,或者如果上一次调用 SQLBulkOperations 中的 Operation 参数不是 SQL_ADD、SQL_UPDATE_BY_BOOKMARK 或 SQL_DELETE_BY_BOOKMARK,或者如果上一次调用SQLSetPos 不是 SQL_UPDATE 或 SQL_DELETE,*RowCountPtr 的值是驱动程序定义的。有关详细信息,请参阅确定受影响的行数。
我想这是有道理的,因为它是成批包装的,它的产量是未知的。
但我无法忘记这个应用程序已经运行了两年并且从未遇到过这个问题。客户说他们更改/删除了一些表格数据,然后应用程序失败。我觉得不太可能,经验告诉我他们做了别的事情,没有说什么。