mysql - SQL_ATTR_ROW_NUMBER 的 SQLGetStmtAttr 输出值

标签 mysql postgresql sqlite odbc

TL;TR: 返回成功并且报告的不是实际行号而是其他指标(如 SQL_ROW_NUMBER_UNKNOWN)是否正确?

据我所知,并非所有 ODBC 驱动程序都支持查询 SQL_ATTR_ROW_NUMBER 属性,因此该属性是可选的。

如果驱动程序不支持它,那么 SQLGetStmtAttr 应该返回此代码,我对吗?

HYC00 - Optional feature not implemented

返回成功并且报告的不是实际行号而是其他指示符(例如 SQL_ROW_NUMBER_UNKNOWN)是否正确?

有些 ODBC 驱动程序可以执行此操作,例如 SQLite 3 for ODBC这样做:

static SQLRETURN
drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
           SQLINTEGER bufmax, SQLINTEGER *buflen)
{
...
    case SQL_ATTR_ROW_NUMBER:
    if (s->s3stmt) {
        *uval = (s->s3stmt_rownum < 0) ?
            SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
    } else {
        *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
    }
    *buflen = sizeof (SQLULEN);
    return SQL_SUCCESS;
...
}

这是正确且符合规范的实现吗?

PostgreSQL ODBC driver例如,如果无法确定行位置,则返回 SQL_ERROR

MySQL 连接器/ODBC 驱动程序似乎总是返回 SQL_SUCCESS 以及根据此方案计算的一些值:

case SQL_ATTR_ROW_NUMBER:
    *(SQLUINTEGER *)ValuePtr= stmt->current_row+1;

其中默认值为

stmt->current_row= -1;  /* Before first row */

我一直认为这是为具有 SQL_DIAG_ROW_NUMBER 标识符的 SQLGetDiagField 保留的,根据 ODBC 的 sqlext.h header 中的注释:

/* define for SQL_DIAG_ROW_NUMBER and SQL_DIAG_COLUMN_NUMBER */
#if (ODBCVER >= 0x0300)
#define SQL_NO_ROW_NUMBER                       (-1)
#define SQL_NO_COLUMN_NUMBER                    (-1)
#define SQL_ROW_NUMBER_UNKNOWN                  (-2)
#define SQL_COLUMN_NUMBER_UNKNOWN               (-2)
#endif

或者,也许最安全的选择是也根据 SQL_ROW_NUMBER_UNKNOWN 检查 SQLGetStmtAttr(SQL_ATTR_ROW_NUMBER) 报告的值?

(MSDN 论坛上也有人提出了同样的问题,here。)

最佳答案

司机返回完全有效

HYC00 - 可选功能未实现

在这种情况下如果它没有实现它。如果当前行号未知或无法确定,驱动程序也可能返回 0。

驱动程序不应返回负数(即 SQL_ROW_NUMBER_UNKNOWN),因为 SQL_ATTR_ROW_NUMBER 的类型被定义为 SQLULEN(也称为无符号数)。您指出的定义:

/* define for SQL_DIAG_ROW_NUMBER and SQL_DIAG_COLUMN_NUMBER */
#if (ODBCVER >= 0x0300)
#define SQL_NO_ROW_NUMBER                       (-1)
#define SQL_NO_COLUMN_NUMBER                    (-1)
#define SQL_ROW_NUMBER_UNKNOWN                  (-2)
#define SQL_COLUMN_NUMBER_UNKNOWN               (-2)
#endif

实际上与发生错误时的诊断有关。有时您可以追踪发生错误的列和行,或者如果没有与错误关联的行/列或者驱动程序无法确定行/列,则驱动程序可以返回这些定义。

在这种情况下,SQLite 3 实现是错误的,MySQL 驱动程序似乎是正确的,因为它始终能够计算并返回当前行号。

请问这个问题背后的动机是什么?您是想自己构建 ODBC 驱动程序还是围绕该驱动程序构建应用程序?

关于mysql - SQL_ATTR_ROW_NUMBER 的 SQLGetStmtAttr 输出值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33940294/

相关文章:

android - 从 assetu 创建的数据库

php - 如何添加表单提交时间

mysql - 通过命令行导入 MySQL 时忽略列数据

mysql - 在 SQL 中计算 2,3 四分位数平均值

postgresql - 在 PostgreSQL 中快速搜索标签(数组、GIN、seqscan)

android - 如何在sqlite中删除数据库?

javascript - Sequelize 原始查询格式日期时间

java - Postgresql 格式化日期

postgresql - 在 sql 中使用 Windows 函数运行总计对于相同的数据具有相同的结果

sql - 将 SQLite DB 文件转换为 "LINQ to SQL",如 SQLMetal.exe