SQLColAttribute 函数

一致性
引入的版本:ODBC 3.0 标准符合性:ISO 92

总结
SQLColAttribute 返回结果集中列的描述符信息。 描述符信息以字符串、描述符相关值或整数值的形式返回。

注意

有关 Driver Manager 将此函数映射到 ODBC 3 时的内容的详细信息。x 应用程序正在使用 ODBC 2。x 驱动程序,请参阅 映射替换函数以实现应用程序的向后兼容性。

语法

  
SQLRETURN SQLColAttribute (  
      SQLHSTMT        StatementHandle,  
      SQLUSMALLINT    ColumnNumber,  
      SQLUSMALLINT    FieldIdentifier,  
      SQLPOINTER      CharacterAttributePtr,  
      SQLSMALLINT     BufferLength,  
      SQLSMALLINT *   StringLengthPtr,  
      SQLLEN *        NumericAttributePtr);  

参数

StatementHandle
[输入]语句句柄。

ColumnNumber
[输入]要从中检索字段值的 IRD 中的记录数。 此参数对应于结果数据的列号,从 1 开始,按递增列顺序按顺序排序。 可以按任意顺序描述列。

可以在此参数中指定列 0,但除SQL_DESC_TYPE和SQL_DESC_OCTET_LENGTH之外的所有值都将返回未定义的值。

FieldIdentifier
[输入]描述符句柄。 此句柄定义应查询 IRD 中的哪些字段(例如,SQL_COLUMN_TABLE_NAME)。

CharacterAttributePtr
[输出]指向缓冲区的指针,如果字段是字符串,则返回 IRD ColumnNumber 行的 FieldIdentifier 字段中的值。 否则,该字段未使用。

如果 CharacterAttributePtr 为 NULL,StringLengthPtr 仍将返回可用于在 CharacterAttributePtr 指向的缓冲区中返回的字节总数(不包括字符数据的 null 终止字符)。

BufferLength
[输入]如果 FieldIdentifier 是 ODBC 定义的字段,并且 CharacterAttributePtr 指向字符串或二进制缓冲区,则此参数应为 *CharacterAttributePtr 的长度。 如果 FieldIdentifier 是 ODBC 定义的字段,并且 *CharacterAttributePtr 是整数,则忽略此字段。 如果 *CharacterAttributePtr 是 Unicode 字符串(调用 SQLColAttributeW 时),BufferLength 参数必须是偶数。 如果 FieldIdentifier 是驱动程序定义的字段,则应用程序通过设置 BufferLength 参数来指示字段的性质。 BufferLength 可以具有以下值:

  • 如果 CharacterAttributePtr 是指向指针的指针, BufferLength 应具有值SQL_IS_POINTER。

  • 如果 CharacterAttributePtr 是指向字符串的指针, BufferLength 是缓冲区的长度。

  • 如果 CharacterAttributePtr 是指向二进制缓冲区的指针,则应用程序会将 SQL_LEN_BINARY_ATTR(length) 宏的结果置于 BufferLength。 这会在 BufferLength放置负值。

  • 如果 CharacterAttributePtr 是指向固定长度数据类型的指针, BufferLength 必须是下列类型之一:SQL_IS_INTEGER、SQL_IS_UINTEGER、SQL_IS_SMALLINT或SQL_IS_USMALLINT。

StringLengthPtr
[输出]指向可在 *CharacterAttributePtr 中返回的可用字节总数(不包括字符数据的 null 终止字节)的缓冲区的指针。

对于字符数据,如果可返回的字节数大于或等于 BufferLength,则 *CharacterAttributePtr 中的描述符信息将被截断为 BufferLength 减去 null 终止字符的长度,并由驱动程序以 null 结尾。

对于所有其他类型的数据,忽略 BufferLength 的值,驱动程序假定 *CharacterAttributePtr 的大小为 32 位。

NumericAttributePtr
[输出]指向整数缓冲区的指针,如果字段是数字描述符类型,则返回 IRD ColumnNumber 行的 FieldIdentifier 字段中的值,例如SQL_DESC_COLUMN_LENGTH。 否则,该字段未使用。 请注意,某些驱动程序可能只写入较低的 32 位或 16 位缓冲区,并使高阶位保持不变。 因此,应用程序应在调用此函数之前将值初始化为 0。

返回

SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_STILL_EXECUTING、SQL_ERROR或SQL_INVALID_HANDLE。

诊断

当 SQLColAttribute 返回SQL_ERROR或SQL_SUCCESS_WITH_INFO时,可以通过使用 handleType of SQL_HANDLE_STMT 和 StatementHandle 句柄调用 SQLGetDiagRec 来获取关联的 SQLSTATE 值。 下表列出了 SQLColAttribute 通常返回的 SQLSTATE 值,并解释此函数上下文中的每个值;表示法“(DM)”位于驱动程序管理器返回的 SQLSTATE 的说明之前。 除非另有说明,否则与每个 SQLSTATE 值关联的返回代码SQL_ERROR。

SQLSTATE 错误 说明
01000 常规警告 特定于驱动程序的信息性消息。 (函数返回SQL_SUCCESS_WITH_INFO。)
01004 字符串数据,右截断 缓冲区 *CharacterAttributePtr 不够大,无法返回整个字符串值,因此字符串值被截断。 未构造的字符串值的长度在 *StringLengthPtr 中返回。 (函数返回SQL_SUCCESS_WITH_INFO。)
07005 准备的语句不是 游标规范 StatementHandle 关联的语句未返回结果集,并且 FieldIdentifier 未SQL_DESC_COUNT。 没有要描述的列。
07009 描述符索引无效 (DM) ColumnNumber 指定的值等于 0,SQL_ATTR_USE_BOOKMARKS语句属性SQL_UB_OFF。

为参数 ColumnNumber 指定的值大于结果集中的列数。
HY000 常规错误 发生错误:没有特定的 SQLSTATE,也没有定义特定于实现的 SQLSTATE。 SQLGetDiagField 从诊断数据结构返回的错误消息描述错误及其原因。
HY001 内存分配错误 驱动程序无法分配支持执行或完成函数所需的内存。
HY008 操作已取消 StatementHandle 启用了异步处理。 调用了该函数,在完成执行之前,对 StatementHandle 调用了 SQLCancel 或 SQLCancelHandle。 然后,在 StatementHandle再次调用该函数。

调用了函数,在完成执行之前,SQLCancel 或 SQLCancelHandle 从多线程应用程序中的不同线程调用 StatementHandle
HY010 函数序列错误 (DM) 为与 StatementHandle 关联的连接句柄调用异步执行函数。 调用 SQLColAttribute 时,此异步函数仍在执行。

(DM) 为 StatementHandle 调用了 SQLExecuteSQLExecDirectSQLMoreResults,并返回了SQL_PARAM_DATA_AVAILABLE。 在检索所有流式处理参数的数据之前调用此函数。

(DM) 在调用 SQLPrepareSQLExecDirect 或 StatementHandle目录函数之前调用了该函数。

(DM) 为 StatementHandle 调用异步执行函数(而不是此函数),并在调用此函数时仍在执行。

(DM) 为 StatementHandle 调用了 SQLExecuteSQLExecDirectSQLBulkOperationsSQLSetPos,并返回了SQL_NEED_DATA。 在为所有数据执行参数或列发送数据之前调用此函数。
HY013 内存管理错误 无法处理函数调用,因为基础内存对象无法访问,可能是因为内存条件低。
HY090 字符串或缓冲区长度无效 (DM) *CharacterAttributePtr 是一个字符串,BufferLength 小于 0,但不等于SQL_NTS。
HY091 描述符字段标识符无效 为参数 FieldIdentifier 指定的值不是定义的值之一,也不是实现定义的值。
HY117 连接因未知事务状态而挂起。 仅允许断开连接和只读函数。 (DM) 有关挂起状态的详细信息,请参阅 SQLEndTran 函数
HYC00 驱动程序不支持 驱动程序不支持为参数 FieldIdentifier 指定的值。
HYT01 超过连接超时时间 在数据源响应请求之前,连接超时期限已过期。 连接超时期限通过 SQLSetConnectAttr 设置,SQL_ATTR_CONNECTION_TIMEOUT。
IM001 驱动程序不支持此函数 (DM) 与 StatementHandle 关联的驱动程序不支持该函数。
IM017 在异步通知模式下禁用轮询 每当使用通知模型时,轮询将被禁用。
IM018 尚未调用 SQLCompleteAsync 来完成此句柄上的上一个异步操作。 如果句柄上的上一个函数调用返回SQL_STILL_EXECUTING并且启用通知模式, 则必须在句柄上调用 SQLCompleteAsync 才能执行后期处理并完成操作。

在 SQLPrepare 之后和 SQLExecute 之前调用时,SQLColAttribute 可以返回 SQLPrepareSQLExecute 可以返回的任何 SQLSTATE,具体取决于数据源何时评估与 StatementHandle 关联的 SQL 语句。

出于性能原因,应用程序在执行语句之前不应调用 SQLColAttribute

注释

有关应用程序如何使用 SQLColAttribute 返回的信息的信息,请参阅结果集元数据

SQLColAttribute 返回 *NumericAttributePtr 或 *CharacterAttributePtr 中的信息。 整数信息以 *NumericAttributePtr 的形式作为 SQLLEN 值返回;所有其他信息格式均以 *CharacterAttributePtr 返回。 在 *NumericAttributePtr 中返回信息时,驱动程序将忽略 CharacterAttributePtrBufferLengthStringLengthPtr。 在 *CharacterAttributePtr 中返回信息时,驱动程序将忽略 NumericAttributePtr

SQLColAttribute 从 IRD 的描述符字段返回值。 该函数使用语句句柄而不是描述符句柄调用。 还可以通过使用适当的 IRD 句柄调用 SQLGetDescField 来检索 SQLColAttribute 为本节后面列出的 FieldIdentifier 值返回的值。

当前定义的描述符字段、引入它们的 ODBC 版本以及返回其信息的参数将在本节后面部分显示:驱动程序可以定义更多的描述符类型,以利用不同的数据源。

ODBC 3。x 驱动程序必须为每个描述符字段返回一个值。 如果描述符字段不适用于驱动程序或数据源,除非另有说明,否则驱动程序在 *StringLengthPtr 中返回 0 或 *CharacterAttributePtr 中的空字符串。

向后兼容性

ODBC 3。x 函数 SQLColAttribute 替换已弃用的 ODBC 2。x 函数 SQLColAttributes。 将 SQLColAttributes 映射到 SQLColAttribute 时(当 ODBC 2 时)。x 应用程序正在使用 ODBC 3。x 驱动程序),或将 SQLColAttribute 映射到 SQLColAttributes(当 ODBC 3 时)。x 应用程序正在使用 ODBC 2。x 驱动程序),驱动程序管理器传递 FieldIdentifier 的值,将其映射到新值,或返回错误,如下所示:

注意

ODBC 3 中 FieldIdentifier 值中使用的前缀。x 已从 ODBC 2 中使用的更改。x. 新前缀为“SQL_DESC”;旧前缀为“SQL_COLUMN”。

  • 如果 ODBC 2 的 #define 值。x FieldIdentifierODBC 3 的 #define 值相同。x FieldIdentifier,函数调用中的值刚刚传递。

  • ODBC 2 的 #define 值。x FieldIdentifiers SQL_COLUMN_LENGTH、SQL_COLUMN_PRECISION 和 SQL_COLUMN_SCALE 不同于 ODBC 3 的 #define 值。x FieldIdentifiers SQL_DESC_PRECISION、SQL_DESC_SCALE 和 SQL_DESC_LENGTH。 ODBC 2。x 驱动程序只需要支持 ODBC 2。x 值。 ODBC 3。x 驱动程序必须同时支持这三 个 FieldIdentifier 的“SQL_COLUMN”和“SQL_DESC”值。 这些值不同,因为 ODBC 3 中定义了精度、小数位数和长度。x 而不是在 ODBC 2 中。x. 有关详细信息,请参阅 列大小、小数位数、传输八进制数长度和显示大小

  • 如果 ODBC 2 的 #define 值。x FieldIdentifier 不同于 ODBC 3 的 #define 值。x FieldIdentifier,与 COUNT、NAME 和 NULLABLE 值一样,函数调用中的值将映射到相应的值。 例如,SQL_COLUMN_COUNT映射到SQL_DESC_COUNT,SQL_DESC_COUNT映射到SQL_COLUMN_COUNT,具体取决于映射的方向。

  • 如果 FieldIdentifier 是 ODBC 3 中的新值。x,ODBC 2 中没有相应的值。x,在 ODBC 3 时不会映射它。x 应用程序在对 ODBC 2 中的 SQLColAttribute 的调用中使用它。x 驱动程序,调用将返回 SQLSTATE HY091 (描述符字段标识符无效)。

下表列出了 SQLColAttribute 返回的描述符类型。 NumericAttributePtr 值的类型SQLLEN *

FieldIdentifier 信息

返回 in
说明
SQL_DESC_AUTO_UNIQUE_VALUE (ODBC 1.0) NumericAttributePtr 如果列是自动创建列,则SQL_TRUE。

如果列不是自动增补列或不是数值,则SQL_FALSE。

此字段仅适用于数值数据类型列。 应用程序可以将值插入包含自动创建列的行中,但通常无法更新列中的值。

在自动创建列中插入时,插入时会将唯一值插入到列中。 增量未定义,但特定于数据源。 应用程序不应假定自动创建列从任何特定点开始或按任何特定值递增。
SQL_DESC_BASE_COLUMN_NAME (ODBC 3.0) CharacterAttributePtr 结果集列的基列名称。 如果基列名不存在(如表达式的列的情况),则此变量包含一个空字符串。

此信息是从 IRD 的SQL_DESC_BASE_COLUMN_NAME记录字段返回的,该字段是只读字段。
SQL_DESC_BASE_TABLE_NAME (ODBC 3.0) CharacterAttributePtr 包含列的基表的名称。 如果无法定义基表名称或不适用,则此变量包含一个空字符串。

此信息从 IRD 的SQL_DESC_BASE_TABLE_NAME记录字段返回,该字段是只读字段。
SQL_DESC_CASE_SENSITIVE (ODBC 1.0) NumericAttributePtr 如果列被视为排序规则和比较区分大小写,SQL_TRUE。

如果列不被视为排序规则和比较区分大小写或非字符,则SQL_FALSE。
SQL_DESC_CATALOG_NAME (ODBC 2.0) CharacterAttributePtr 包含列的表的目录。 如果列是表达式,或者列是视图的一部分,则返回的值是实现定义的。 如果数据源不支持目录或无法确定目录名称,则返回空字符串。 此 VARCHAR 记录字段不限于 128 个字符。
SQL_DESC_CONCISE_TYPE (ODBC 1.0) NumericAttributePtr 简洁的数据类型。

对于日期/时间数据类型和间隔数据类型,此字段返回简洁的数据类型;例如,SQL_TYPE_TIME或SQL_INTERVAL_YEAR。 (有关详细信息,请参阅 附录 D:数据类型中的数据类型标识符和描述符

此信息从 IRD 的SQL_DESC_CONCISE_TYPE记录字段返回。
SQL_DESC_COUNT (ODBC 1.0) NumericAttributePtr 结果集中可用的列数。 如果结果集中没有列,则返回 0。 ColumnNumber 参数中的值将被忽略。

此信息是从 IRD 的SQL_DESC_COUNT标头字段返回的。
SQL_DESC_DISPLAY_SIZE (ODBC 1.0) NumericAttributePtr 显示列中数据所需的最大字符数。 有关显示大小的详细信息,请参阅 附录 D:数据类型中的列大小、小数位数、传输八进制数长度和显示大小
SQL_DESC_FIXED_PREC_SCALE (ODBC 1.0) NumericAttributePtr 如果列具有特定于数据源的固定精度和非零刻度,则SQL_TRUE。

如果列没有特定于数据源的固定精度和非零刻度,则SQL_FALSE。
SQL_DESC_LABEL (ODBC 2.0) CharacterAttributePtr 列标签或标题。 例如,名为 EmpName 的列可能标记为“员工姓名”,或者可能使用别名进行标记。

如果列没有标签,则返回列名称。 如果列未标记且未命名,则返回空字符串。
SQL_DESC_LENGTH (ODBC 3.0) NumericAttributePtr 一个数值,该值是字符串或二进制数据类型的最大或实际字符长度。 它是固定长度数据类型的最大字符长度,或者是可变长度数据类型的实际字符长度。 其值始终排除结束字符串的 null 终止字节。

此信息从 IRD 的SQL_DESC_LENGTH记录字段返回。

有关长度的详细信息,请参阅 附录 D:数据类型中的列大小、小数位数、传输八进制数长度和显示大小
SQL_DESC_LITERAL_PREFIX (ODBC 3.0) CharacterAttributePtr 此 VARCHAR(128) 记录字段包含驱动程序识别为此数据类型文本前缀的字符或字符。 此字段包含文本前缀不适用的数据类型的空字符串。 有关详细信息,请参阅 文本前缀和后缀
SQL_DESC_LITERAL_SUFFIX (ODBC 3.0) CharacterAttributePtr 此 VARCHAR(128) 记录字段包含驱动程序识别为此数据类型文本文本的后缀的字符或字符。 此字段包含文本后缀不适用的数据类型的空字符串。 有关详细信息,请参阅 文本前缀和后缀
SQL_DESC_LOCAL_TYPE_NAME (ODBC 3.0) CharacterAttributePtr 此 VARCHAR(128) 记录字段包含可能与数据类型的常规名称不同的数据类型的任何本地化(本机语言)名称。 如果没有本地化名称,则返回空字符串。 此字段仅用于显示目的。 字符串的字符集依赖于区域设置,通常是服务器的默认字符集。
SQL_DESC_NAME (ODBC 3.0) CharacterAttributePtr 列别名(如果适用)。 如果列别名不适用,则返回列名称。 在任一情况下,SQL_DESC_UNNAMED都设置为SQL_NAMED。 如果没有列名或列别名,则返回空字符串,SQL_DESC_UNNAMED设置为SQL_UNNAMED。

此信息是从 IRD 的SQL_DESC_NAME记录字段返回的。
SQL_DESC_NULLABLE (ODBC 3.0) NumericAttributePtr 如果列可以具有 NULL 值,SQL_ NULLABLE;如果列没有 NULL 值,则SQL_NO_NULLS;或者,如果不知道列是否接受 NULL 值,则为SQL_NULLABLE_UNKNOWN。

此信息是从 IRD 的SQL_DESC_NULLABLE记录字段返回的。
SQL_DESC_NUM_PREC_RADIX (ODBC 3.0) NumericAttributePtr 如果SQL_DESC_TYPE字段中的数据类型是近似数值数据类型,则此 SQLINTEGER 字段包含值 2,因为SQL_DESC_PRECISION字段包含位数。 如果SQL_DESC_TYPE字段中的数据类型是确切的数字数据类型,则此字段包含值 10,因为SQL_DESC_PRECISION字段包含小数位数。 对于所有非数值数据类型,此字段设置为 0。
SQL_DESC_OCTET_LENGTH (ODBC 3.0) NumericAttributePtr 字符串或二进制数据类型的长度(以字节为单位)。 对于固定长度字符或二进制类型,这是实际长度(以字节为单位)。 对于可变长度字符或二进制类型,这是最大长度(以字节为单位)。 此值不包括 null 终止符。

此信息从 IRD 的SQL_DESC_OCTET_LENGTH记录字段返回。

有关长度的详细信息,请参阅 附录 D:数据类型中的列大小、小数位数、传输八进制数长度和显示大小
SQL_DESC_PRECISION (ODBC 3.0) NumericAttributePtr 数值数据类型的数值表示适用的精度。 对于数据类型SQL_TYPE_TIME、SQL_TYPE_TIMESTAMP和表示时间间隔的所有间隔数据类型,其值是小数秒分量适用的精度。

此信息从 IRD 的SQL_DESC_PRECISION记录字段返回。
SQL_DESC_SCALE (ODBC 3.0) NumericAttributePtr 一个数值,该值是数值数据类型的适用小数位数。 对于 DECIMAL 和 NUMERIC 数据类型,这是定义的小数位数。 它未为所有其他数据类型定义。

此信息是从 IRD 的 SCALE 记录字段返回的。
SQL_DESC_SCHEMA_NAME (ODBC 2.0) CharacterAttributePtr 包含列的表的架构。 如果列是表达式,或者列是视图的一部分,则返回的值是实现定义的。 如果数据源不支持架构或无法确定架构名称,则返回空字符串。 此 VARCHAR 记录字段不限于 128 个字符。
SQL_DESC_SEARCHABLE (ODBC 1.0) NumericAttributePtr 如果不能在 WHERE 子句中使用列,则SQL_PRED_NONE。 (这与 ODBC 2 中的SQL_UNSEARCHABLE值相同。x.)

如果列可以在 WHERE 子句中使用,但只能与 LIKE 谓词一起使用,则SQL_PRED_CHAR。 (这与 ODBC 2 中的SQL_LIKE_ONLY值相同。x.)

SQL_PRED_BASIC如果列可用于 WHERE 子句以及除 LIKE 之外的所有比较运算符。 (这与 ODBC 2 中的SQL_EXCEPT_LIKE值相同。x.)

如果列可用于具有任何比较运算符的 WHERE 子句中,则SQL_PRED_SEARCHABLE。

SQL_LONGVARCHAR类型的列和SQL_LONGVARBINARY通常返回SQL_PRED_CHAR。
SQL_DESC_TABLE_NAME (ODBC 2.0) CharacterAttributePtr 包含该列的表的名称。 如果列是表达式,或者列是视图的一部分,则返回的值是实现定义的。

如果无法确定表名,则返回空字符串。
SQL_DESC_TYPE (ODBC 3.0) NumericAttributePtr 一个指定 SQL 数据类型的数值。

当 ColumnNumber 等于 0 时,将为可变长度书签返回SQL_BINARY,并且为固定长度书签返回SQL_INTEGER。

对于日期/时间和间隔数据类型,此字段返回详细数据类型:SQL_DATETIME或SQL_INTERVAL。 (有关详细信息,请参阅 附录 D 中的数据类型标识符和描述符 :数据类型。

此信息从 IRD 的SQL_DESC_TYPE记录字段返回。 注意: 针对 ODBC 2 工作。x 驱动程序,请改用SQL_DESC_CONCISE_TYPE。
SQL_DESC_TYPE_NAME (ODBC 1.0) CharacterAttributePtr 数据源依赖数据类型名称;例如,“CHAR”、“VARCHAR”、“MONEY”、“LONG VARBINARY”或“CHAR() FOR BIT DATA”。

如果类型未知,则返回空字符串。
SQL_DESC_UNNAMED (ODBC 3.0) NumericAttributePtr SQL_NAMED或SQL_UNNAMED。 如果 IRD 的SQL_DESC_NAME字段包含列别名或列名,则返回SQL_NAMED。 如果没有列名或列别名,则返回SQL_UNNAMED。

此信息从 IRD 的SQL_DESC_UNNAMED记录字段返回。
SQL_DESC_UNSIGNED (ODBC 1.0) NumericAttributePtr 如果列为无符号(或不带数字),则SQL_TRUE。

如果列已签名,则SQL_FALSE。
SQL_DESC_UPDATABLE (ODBC 1.0) NumericAttributePtr 列由定义的常量的值描述:

SQL_ATTR_READONLY SQL_ATTR_WRITE SQL_ATTR_READWRITE_UNKNOWN

SQL_DESC_UPDATABLE描述结果集中列的可更新性,而不是基表中的列。 结果集列所基于的基列的可更新性可能与此字段中的值不同。 列是否可以根据数据类型、用户特权和结果集本身的定义进行更新。 如果不清楚列是否可更新,应返回SQL_ATTR_READWRITE_UNKNOWN。

SQLColAttribute 是 SQLDescribeCol可扩展替代方法。 SQLDescribeCol 基于 ANSI-89 SQL 返回一组固定的描述符信息。 SQLColAttribute 允许访问 ANSI SQL-92 和 DBMS 供应商扩展中提供的更广泛的描述符信息集。

有关以下内容的信息 请参阅
将缓冲区绑定到结果集中的列 SQLBindCol 函数
取消语句处理 SQLCancel 函数
返回有关结果集中的列的信息 SQLDescribeCol 函数
提取数据块或滚动结果集 SQLFetchScroll 函数
提取多行数据 SQLFetch 函数

示例

以下示例代码不释放句柄和连接。 有关代码示例来释放句柄和语句,请参阅 SQLFreeHandle 函数示例 ODBC 程序和 SQLFreeStmt 函数

// SQLColAttibute.cpp  
// compile with: user32.lib odbc32.lib  
  
#define UNICODE  
  
#include <windows.h>  
#include <sqlext.h>  
#include <strsafe.h>  
  
struct DataBinding {  
   SQLSMALLINT TargetType;  
   SQLPOINTER TargetValuePtr;  
   SQLINTEGER BufferLength;  
   SQLLEN StrLen_or_Ind;  
};  
  
void printStatementResult(SQLHSTMT hstmt) {  
   int bufferSize = 1024, i;  
   SQLRETURN retCode;  
   SQLSMALLINT numColumn = 0, bufferLenUsed;
   
   retCode = SQLNumResultCols(hstmt, &numColumn);  
   
   SQLPOINTER* columnLabels = (SQLPOINTER *)malloc( numColumn * sizeof(SQLPOINTER*) );  
   struct DataBinding* columnData = (struct DataBinding*)malloc( numColumn * sizeof(struct DataBinding) );  
  
   printf( "Columns from that table:\n" );  
   for ( i = 0 ; i < numColumn ; i++ ) {  
      columnLabels[i] = (SQLPOINTER)malloc( bufferSize*sizeof(char) );  
  
      retCode = SQLColAttribute(hstmt, (SQLUSMALLINT)i + 1, SQL_DESC_LABEL, columnLabels[i], (SQLSMALLINT)bufferSize, &bufferLenUsed, NULL);  
      wprintf( L"Column %d: %s\n", i, (wchar_t*)columnLabels[i] );  
   }  
  
   // allocate memory for the binding  
   for ( i = 0 ; i < numColumn ; i++ ) {  
      columnData[i].TargetType = SQL_C_CHAR;  
      columnData[i].BufferLength = (bufferSize+1);  
      columnData[i].TargetValuePtr = malloc( sizeof(unsigned char)*columnData[i].BufferLength );  
   }  
  
   // setup the binding   
   for ( i = 0 ; i < numColumn ; i++ ) {  
      retCode = SQLBindCol(hstmt, (SQLUSMALLINT)i + 1, columnData[i].TargetType,   
         columnData[i].TargetValuePtr, columnData[i].BufferLength, &(columnData[i].StrLen_or_Ind));  
   }  
  
   printf( "Data from that table:\n" );  
   // fetch the data and print out the data  
   for ( retCode = SQLFetch(hstmt) ; retCode == SQL_SUCCESS || retCode == SQL_SUCCESS_WITH_INFO ; retCode = SQLFetch(hstmt) ) {  
      int j;  
      for ( j = 0 ; j < numColumn ; j++ )  
         wprintf( L"%s: %hs\n", columnLabels[j], columnData[j].TargetValuePtr );  
      printf( "\n" );  
   }  
   printf( "\n" );   
}  
  
int main() {  
   int bufferSize = 1024, i, count = 1, numCols = 5;  
   wchar_t firstTableName[1024], * dbName = (wchar_t *)malloc( sizeof(wchar_t)*bufferSize ), * userName = (wchar_t *)malloc( sizeof(wchar_t)*bufferSize );  
   HWND desktopHandle = GetDesktopWindow();   // desktop's window handle  
   SQLWCHAR connStrbuffer[1024];  
   SQLSMALLINT connStrBufferLen, bufferLen;  
   SQLRETURN retCode;  
  
   SQLHENV henv = NULL;   // Environment     
   SQLHDBC hdbc = NULL;   // Connection handle  
   SQLHSTMT hstmt = NULL;   // Statement handle  
  
   struct DataBinding* catalogResult = (struct DataBinding*) malloc( numCols * sizeof(struct DataBinding) );  
   SQLWCHAR* selectAllQuery = (SQLWCHAR *)malloc( sizeof(SQLWCHAR) * bufferSize );  
  
   // connect to database  
   retCode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);  
   retCode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLCHAR *)(void*)SQL_OV_ODBC3, -1);  
   retCode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);  
   retCode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)10, 0);  
   retCode = SQLDriverConnect(hdbc, desktopHandle, L"Driver={SQL Server}", SQL_NTS, connStrbuffer, 1025, &connStrBufferLen, SQL_DRIVER_PROMPT);  
   retCode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);  
  
   // display the database information  
   retCode = SQLGetInfo(hdbc, SQL_DATABASE_NAME, dbName, (SQLSMALLINT)bufferSize, (SQLSMALLINT *)&bufferLen);  
   retCode = SQLGetInfo(hdbc, SQL_USER_NAME, userName, (SQLSMALLINT)bufferSize, &bufferLen);  
  
   for ( i = 0 ; i < numCols ; i++ ) {  
      catalogResult[i].TargetType = SQL_C_CHAR;  
      catalogResult[i].BufferLength = (bufferSize + 1);  
      catalogResult[i].TargetValuePtr = malloc( sizeof(unsigned char)*catalogResult[i].BufferLength );  
   }  
  
   // Set up the binding. This can be used even if the statement is closed by closeStatementHandle  
   for ( i = 0 ; i < numCols ; i++ )  
      retCode = SQLBindCol(hstmt, (SQLUSMALLINT)i + 1, catalogResult[i].TargetType, catalogResult[i].TargetValuePtr, catalogResult[i].BufferLength, &(catalogResult[i].StrLen_or_Ind));  
  
   retCode = SQLTables( hstmt, (SQLWCHAR*)SQL_ALL_CATALOGS, SQL_NTS, L"", SQL_NTS, L"", SQL_NTS, L"", SQL_NTS );  
   retCode = SQLFreeStmt(hstmt, SQL_CLOSE);  
  
   retCode = SQLTables( hstmt, dbName, SQL_NTS, userName, SQL_NTS, L"%", SQL_NTS, L"TABLE", SQL_NTS );  
  
   for ( retCode = SQLFetch(hstmt) ; retCode == SQL_SUCCESS || retCode == SQL_SUCCESS_WITH_INFO ; retCode = SQLFetch(hstmt), ++count )  
      if ( count == 1 )  
         StringCchPrintfW( firstTableName, 1024, L"%hs", catalogResult[2].TargetValuePtr );  
   retCode = SQLFreeStmt(hstmt, SQL_CLOSE);  
  
   wprintf( L"Select all data from the first table (%s)\n", firstTableName );  
   StringCchPrintfW( selectAllQuery, bufferSize, L"SELECT * FROM %s", firstTableName );  
  
   retCode = SQLExecDirect(hstmt, selectAllQuery, SQL_NTS);  
   printStatementResult(hstmt);  
}  

另请参阅

ODBC API 参考
ODBC 头文件
示例 ODBC 程序