SQLColAttribute 函数

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

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

注意

有关驱动程序管理器在 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 仍将返回总字节数 (不包括字符数据的 null 终止字符数,) 字符数据可在 CharacterAttributePtr 指向的缓冲区中返回。

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

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

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

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

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

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

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

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

NumericAttributePtr
[输出]指向整数缓冲区的指针,如果字段是数值描述符类型(如 SQL_DESC_COLUMN_LENGTH),则返回 IRD ColumnNumber 行的 FieldIdentifier 字段中的值。 否则,字段未使用。 请注意,某些驱动程序可能只写入缓冲区的较低 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 SQL_HANDLE_STMT 和 Handle ofStatementHandle 调用 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 上再次调用函数。

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

(DM) SQLExecuteSQLExecDirectSQLMoreResults 已为 StatementHandle 调用并返回SQL_PARAM_DATA_AVAILABLE。 此函数是在检索所有流参数的数据之前调用的。

(DM) 在调用 SQLPrepareSQLExecDirectStatementHandle 的目录函数之前调用了函数。

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

(DM) SQLExecuteSQLExecDirectSQLBulkOperationsSQLSetPos 已为 StatementHandle 调用,并返回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 的描述符字段中返回值。 函数是使用语句句柄而不是描述符句柄调用的。 SQLColAttribute 为本节后面列出的 FieldIdentifier 值返回的值也可以通过使用适当的 IRD 句柄调用 SQLGetDescField 来检索。

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

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

Backward Compatibility

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

注意

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

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

  • ODBC 2 的#define 值。xFieldIdentifiers SQL_COLUMN_LENGTH、SQL_COLUMN_PRECISION 和 SQL_COLUMN_SCALE 不同于 ODBC 3 的#define 值。xFieldIdentifiers 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 中,精度、小数位数和长度的定义不同。 ODBC 2 中的 x。x. 有关详细信息,请参阅 列大小、十进制数字、传输八进制数长度和显示大小

  • 如果 #define ODBC 2 的值。xFieldIdentifier 不同于 ODBC 3 的#define 值。xFieldIdentifier 与 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 信息

说明
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 简洁的数据类型。

对于 datetime 和 interval 数据类型,此字段返回简洁的数据类型;例如,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.)

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

SQL_PRED_BASIC列是否可以在 WHERE 子句中使用除 LIKE 以外的所有比较运算符。 (这与 ODBC 2 中的SQL_EXCEPT_LIKE值相同。x.)

SQL_PRED_SEARCHABLE列是否可以在 WHERE 子句中使用任何比较运算符。

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。

对于 datetime 和 interval 数据类型,此字段返回详细数据类型: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。

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

有关以下方面的信息 请参阅
将缓冲区绑定到结果集中的列 SQLBindCol 函数
取消语句处理 SQLCancel 函数
返回有关结果集中列的信息 SQLDescribeCol 函数
提取数据块或滚动浏览结果集 SQLFetchScroll Function(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 程序