SQLForeignKeys 函数

一致性
引入的版本:ODBC 1.0 标准符合性:ODBC

摘要
SQLForeignKeys 可以返回:

  • 指定表中的外键列表 (指定表中引用) 其他表中的主键的列。

  • 引用指定表中主键的其他表中的外键的列表。

驱动程序将每个列表作为指定语句的结果集返回。

语法

  
SQLRETURN SQLForeignKeys(  
     SQLHSTMT       StatementHandle,  
     SQLCHAR *      PKCatalogName,  
     SQLSMALLINT    NameLength1,  
     SQLCHAR *      PKSchemaName,  
     SQLSMALLINT    NameLength2,  
     SQLCHAR *      PKTableName,  
     SQLSMALLINT    NameLength3,  
     SQLCHAR *      FKCatalogName,  
     SQLSMALLINT    NameLength4,  
     SQLCHAR *      FKSchemaName,  
     SQLSMALLINT    NameLength5,  
     SQLCHAR *      FKTableName,  
     SQLSMALLINT    NameLength6);  

参数

StatementHandle
[输入]语句句柄。

PKCatalogName
[输入]主键表目录名称。 如果驱动程序支持某些表的目录,但不支持其他表的目录,例如当驱动程序从不同的 DBMS 检索数据时,空字符串 (“”) 表示那些没有目录的表。 PKCatalogName 不能包含字符串搜索模式。

如果 SQL_ATTR_METADATA_ID 语句属性设置为 SQL_TRUE, 则 PKCatalogName 被视为标识符,其大小写不重要。 如果它是SQL_FALSE, 则 PKCatalogName 是一个普通参数;它按字面处理,其大小写很重要。 有关详细信息,请参阅 目录函数中的参数

NameLength1
[输入]*PKCatalogName 的长度(以字符为单位)。

PKSchemaName
[输入]主键表架构名称。 如果驱动程序支持某些表的架构,但不支持其他表的架构,例如当驱动程序从不同的 DBMS 检索数据时,空字符串 (“”) 表示那些没有架构的表。 PKSchemaName 不能包含字符串搜索模式。

如果 SQL_ATTR_METADATA_ID 语句属性设置为 SQL_TRUE, 则 PKSchemaName 被视为标识符,其大小写不重要。 如果它是SQL_FALSE, 则 PKSchemaName 是一个普通参数;它按字面处理,其大小写很重要。

NameLength2
[输入]*PKSchemaName 的长度(以字符为单位)。

PKTableName
[输入]主键表名称。 PKTableName 不能包含字符串搜索模式。

如果 SQL_ATTR_METADATA_ID 语句属性设置为 SQL_TRUE, 则 PKTableName 被视为标识符,其大小写不重要。 如果它是SQL_FALSE, 则 PKTableName 是一个普通参数;它按字面处理,其大小写很重要。

NameLength3
[输入]*PKTableName 的长度(以字符为单位)。

FKCatalogName
[输入]外键表目录名称。 如果驱动程序支持某些表的目录,但不支持其他表的目录,例如当驱动程序从不同的 DBMS 检索数据时,空字符串 (“”) 表示那些没有目录的表。 FKCatalogName 不能包含字符串搜索模式。

如果 SQL_ATTR_METADATA_ID 语句属性设置为 SQL_TRUE, 则 FKCatalogName 被视为标识符,其大小写不重要。 如果SQL_FALSE, 则 FKCatalogName 为普通参数;它按字面处理,其大小写很重要。

NameLength4
[输入]*FKCatalogName 的长度(以字符为单位)。

FKSchemaName
[输入]外键表架构名称。 如果驱动程序支持某些表的架构,但不支持其他表的架构,例如当驱动程序从不同的 DBMS 检索数据时,空字符串 (“”) 表示那些没有架构的表。 FKSchemaName 不能包含字符串搜索模式。

如果 SQL_ATTR_METADATA_ID 语句属性设置为 SQL_TRUE, 则 FKSchemaName 被视为标识符,其大小写不重要。 如果它是SQL_FALSE, 则 FKSchemaName 是一个普通参数;它按字面处理,其大小写很重要。

NameLength5
[输入]*FKSchemaName 的长度(以字符为单位)。

FKTableName
[输入]外键表名称。 FKTableName 不能包含字符串搜索模式。

如果 SQL_ATTR_METADATA_ID 语句属性设置为 SQL_TRUE, 则 FKTableName 被视为标识符,其大小写不重要。 如果它是SQL_FALSE, 则 FKTableName 是一个普通参数;它按字面处理,其大小写很重要。

NameLength6
[输入]*FKTableName 的长度(以字符为单位)。

返回

SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_STILL_EXECUTING、SQL_ERROR或SQL_INVALID_HANDLE。

诊断

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

SQLSTATE 错误 描述
01000 常规警告 特定于驱动程序的信息性消息。 (函数返回 SQL_SUCCESS_WITH_INFO.)
08S01 通信链接失败 在函数完成处理之前,驱动程序与驱动程序连接到的数据源之间的通信链接失败。
24000 游标状态无效 在 StatementHandle 上打开了一个游标,并且已调用 SQLFetchSQLFetchScroll。 如果 SQLFetchSQLFetchScroll 未返回SQL_NO_DATA,则驱动程序管理器将返回此错误;如果 SQLFetchSQLFetchScroll 已返回SQL_NO_DATA,则由驱动程序返回此错误。

在 StatementHandle 上打开了游标,但尚未调用 SQLFetchSQLFetchScroll
40001 序列化失败 由于与另一个事务发生资源死锁,事务已回滚。
40003 语句完成未知 关联的连接在执行此函数期间失败,并且无法确定事务的状态。
HY000 常规错误 发生错误,其中没有特定的 SQLSTATE,并且没有定义特定于实现的 SQLSTATE。 *MessageText 缓冲区中 SQLGetDiagRec 返回的错误消息描述了错误及其原因。
HY001 内存分配错误 驱动程序无法分配支持执行或完成函数所需的内存。
HY008 操作已取消 已为 StatementHandle 启用异步处理。 调用了函数,在它完成执行之前,在 StatementHandle 上调用了 SQLCancel 或 SQLCancelHandle,然后在 StatementHandle 上再次调用该函数。

函数已调用,在它完成执行之前, SQLCancelSQLCancelHandle 是从多线程应用程序中的不同线程在 StatementHandle 上调用的。
HY009 null 指针的使用无效 (DM) 参数 PKTableNameFKTableName 都是空指针。

SQL_ATTR_METADATA_ID 语句属性设置为 SQL_TRUE, FKCatalogNamePKCatalogName 参数为空指针, SQL_CATALOG_NAME InfoType 返回支持目录名称。

(DM) SQL_ATTR_METADATA_ID 语句属性设置为 SQL_TRUE, FKSchemaNamePKSchemaNameFKTableNamePKTableName 参数为 null 指针。
HY010 函数序列错误 (DM) 为与 StatementHandle 关联的连接句柄调用了异步执行的函数。 调用 SQLForeignKeys 函数时,此异步函数仍在执行。

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

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

(DM) SQLExecuteSQLExecDirectSQLBulkOperationsSQLSetPos 已为 StatementHandle 调用,并返回SQL_NEED_DATA。 在针对所有数据执行参数或列发送数据之前调用了此函数。
HY013 内存管理错误 无法处理函数调用,因为无法访问基础内存对象,可能是由于内存不足。
HY090 无效的字符串或缓冲区长度 (DM) 其中一个名称长度参数的值小于 0,但不等于SQL_NTS。
其中一个名称长度参数的值超过了相应名称的最大长度值。 (请参阅“注释”。)
HY117 由于事务状态未知,连接已暂停。 仅允许断开连接和只读函数。 (DM) 有关挂起状态的详细信息,请参阅 SQLEndTran 函数
HYC00 未实现可选功能 指定了目录名称,并且驱动程序或数据源不支持目录。

指定了架构名称,驱动程序或数据源不支持架构。
驱动程序或数据源不支持SQL_ATTR_CONCURRENCY和 SQL_ATTR_CURSOR_TYPE 语句属性的当前设置组合。

SQL_ATTR_USE_BOOKMARKS 语句属性设置为 SQL_UB_VARIABLE,SQL_ATTR_CURSOR_TYPE 语句属性设置为驱动程序不支持书签的游标类型。
HYT00 超时时间已到 查询超时期限在数据源返回结果集之前过期。 超时期限是通过 SQLSetStmtAttr SQL_ATTR_QUERY_TIMEOUT设置的。
HYT01 超过连接超时时间 在数据源响应请求之前,连接超时期限已过期。 连接超时期限通过 SQLSetConnectAttr SQL_ATTR_CONNECTION_TIMEOUT设置。
IM001 驱动程序不支持此函数 (DM) 与 StatementHandle 关联的驱动程序不支持 函数。
IM017 在异步通知模式下禁用轮询 每当使用通知模型时,将禁用轮询。
IM018 尚未调用 SQLCompleteAsync 来完成此句柄上的上一个异步操作。 如果对句柄的上一个函数调用返回SQL_STILL_EXECUTING并且启用了通知模式,则必须在句柄上调用 SQLCompleteAsync 以执行后期处理并完成操作。

注释

有关如何使用此函数返回的信息的信息,请参阅 目录数据的使用

如果 *PKTableName 包含表名, SQLForeignKeys 将返回一个结果集,其中包含指定表的主键和引用该表的所有外键。 其他表中的外键列表不包括指向指定表中唯一约束的外键。

如果 *FKTableName 包含表名, SQLForeignKeys 将返回一个结果集,其中包含指定表中指向其他表中主键的所有外键,以及它们引用的其他表中的主键。 指定表中的外键列表不包含引用其他表中唯一约束的外键。

如果 *PKTableName 和 *FKTableName 都包含表名, SQLForeignKeys 将返回 *FKTableName 中指定的表中引用 *PKTableName 中指定的表的主键的外键。 这应该最多是一个键。

注意

有关 ODBC 目录函数的常规用法、参数和返回数据的详细信息,请参阅 目录函数

SQLForeignKeys 以标准结果集的形式返回结果。 如果请求与主键关联的外键,则按FKTABLE_CAT、FKTABLE_SCHEM、FKTABLE_NAME和KEY_SEQ对结果集进行排序。 如果请求与外键关联的主键,则按PKTABLE_CAT、PKTABLE_SCHEM、PKTABLE_NAME和KEY_SEQ对结果集进行排序。 下表列出了结果集中的列。

表中未显示 VARCHAR 列的长度;实际长度取决于数据源。 若要确定PKTABLE_CAT或FKTABLE_CAT、PKTABLE_SCHEM或FKTABLE_SCHEM、PKTABLE_NAME或FKTABLE_NAME以及PKCOLUMN_NAME列或FKCOLUMN_NAME列的实际长度,应用程序可以使用SQL_MAX_CATALOG_NAME_LEN、SQL_MAX_SCHEMA_NAME_LEN、SQL_MAX_TABLE_NAME_LEN和SQL_MAX_COLUMN_NAME_LEN选项调用 SQLGetInfo

以下列已重命名为 ODBC 3*.x.* 列名更改不会影响向后兼容性,因为应用程序按列号绑定。

ODBC 2.0 列 ODBC 3*.x* 列
PKTABLE_QUALIFIER PKTABLE_CAT
PKTABLE_OWNER PKTABLE_SCHEM
FKTABLE_QUALIFIER FK_TABLE_CAT
FKTABLE_OWNER FKTABLE_SCHEM

下表列出了结果集中的列。 驱动程序可以定义列 14 以外的其他列 (REMARKS) 。 应用程序应通过从结果集末尾倒计时(而不是指定显式序号位置)来访问特定于驱动程序的列。 有关详细信息,请参阅 目录函数返回的数据

列名称 列号 数据类型 注释
PKTABLE_CAT (ODBC 1.0) 1 Varchar 主键表目录名称;如果不适用于数据源,则为 NULL。 如果驱动程序支持某些表的目录,但不支持其他表的目录,例如当驱动程序从不同的 DBMS 检索数据时,它将为没有目录的表返回空字符串 (“”) 。
PKTABLE_SCHEM (ODBC 1.0) 2 Varchar 主键表架构名称;如果不适用于数据源,则为 NULL。 如果驱动程序支持某些表的架构,但不支持其他表的架构,例如当驱动程序从不同的 DBMS 检索数据时,它会为没有架构的表返回空字符串 (“”) 。
PKTABLE_NAME (ODBC 1.0) 3 Varchar 非 NULL 主键表名称。
PKCOLUMN_NAME (ODBC 1.0) 4 Varchar 非 NULL 主键列名称。 驱动程序返回没有名称的列的空字符串。
FKTABLE_CAT (ODBC 1.0) 5 Varchar 外键表目录名称;如果不适用于数据源,则为 NULL。 如果驱动程序支持某些表的目录,但不支持其他表的目录,例如当驱动程序从不同的 DBMS 检索数据时,它将为没有目录的表返回空字符串 (“”) 。
FKTABLE_SCHEM (ODBC 1.0) 6 Varchar 外键表架构名称;如果不适用于数据源,则为 NULL。 如果驱动程序支持某些表的架构,但不支持其他表的架构,例如当驱动程序从不同的 DBMS 检索数据时,它会为没有架构的表返回空字符串 (“”) 。
FKTABLE_NAME (ODBC 1.0) 7 Varchar 非 NULL 外键表名称。
FKCOLUMN_NAME (ODBC 1.0) 8 Varchar 非 NULL 外键列名称。 驱动程序返回没有名称的列的空字符串。
KEY_SEQ (ODBC 1.0) 9 Smallint(非 NULL) 键 (中的列序列号从 1) 开始。
UPDATE_RULE (ODBC 1.0) 10 Smallint 当 SQL 操作为 UPDATE 时要应用于外键的操作。 可以具有以下值之一。 (引用的表是具有主键的表;引用表是具有外键的表)

SQL_CASCADE:更新引用表的主键时,引用表的外键也会更新。

SQL_NO_ACTION:如果引用表的主键更新会导致引用表 (“悬空引用”,即引用表中的行在引用表) 中没有对应项,则拒绝更新。 如果引用表的外键更新会引入一个作为引用表主键的值不存在的值,则会拒绝更新。 (此操作与 ODBC 2*.x*.) 中的SQL_RESTRICT操作相同

SQL_SET_NULL:当引用表中的一行或多行以更改主键的一个或多个组件的方式进行更新时,引用表中与主键的已更改组件相对应的外键组件在引用表的所有匹配行中将设置为 NULL。

SQL_SET_DEFAULT:当引用表中的一个或多个行以更改主键的一个或多个组件的方式进行更新时,引用表中与主键的已更改组件相对应的外键组件将设置为引用表的所有匹配行中的适用默认值。

如果不适用于数据源,则为 NULL。
DELETE_RULE (ODBC 1.0) 11 Smallint 当 SQL 操作为 DELETE 时要应用于外键的操作。 可以具有以下值之一。 (引用的表是具有主键的表;引用表是具有外键的表)

SQL_CASCADE:删除引用表中的行时,引用表中的所有匹配行也会被删除。

SQL_NO_ACTION:如果删除引用表中的行会导致引用表 (即引用表中的行在引用表) 中没有对应项,则拒绝更新。 (此操作与 ODBC 2*.x*.) 中的SQL_RESTRICT操作相同

SQL_SET_NULL:删除引用表中的一行或多行时,引用表外键的每个组件在引用表的所有匹配行中都设置为 NULL。

SQL_SET_DEFAULT:删除引用表中的一行或多行时,引用表外键的每个组件将设置为引用表的所有匹配行中适用的默认值。

如果不适用于数据源,则为 NULL。
FK_NAME (ODBC 2.0) 12 Varchar 外键名称。 如果不适用于数据源,则为 NULL。
PK_NAME (ODBC 2.0) 13 Varchar 主键名称。 如果不适用于数据源,则为 NULL。
延迟性 (ODBC 3.0) 14 Smallint SQL_INITIALLY_DEFERRED、SQL_INITIALLY_IMMEDIATE、SQL_NOT_DEFERRABLE。

代码示例

如下表所示,此示例使用三个名为 ORDERS、LINES 和 CUSTOMERS 的表。

ORDERS LINES 客户
ORDERID ORDERID CUSTID
CUSTID LINES 名称
OPENDATE PARTID 地址
售货员 数量 电话
状态

在 ORDERS 表中,CUSTID 标识已向其进行销售的客户。 它是引用 CUSTOMERS 表中 CUSTID 的外键。

在 LINES 表中,ORDERID 标识与行项关联的销售订单。 它是引用 ORDERS 表中 ORDERID 的外键。

此示例调用 SQLPrimaryKeys 以获取 ORDERS 表的主键。 结果集将有一行:下表显示了重要列。

TABLE_NAME COLUMN_NAME KEY_SEQ
ORDERS ORDERID 1

接下来,该示例调用 SQLForeignKeys 以获取引用 ORDERS 表主键的其他表中的外键。 结果集将有一行:下表显示了重要列。

PKTABLE_NAME PKCOLUMN_NAME FKTABLE_NAME FKCOLUMN_NAME KEY_SEQ
ORDERS CUSTID LINES CUSTID 1

最后,该示例调用 SQLForeignKeys 来获取 ORDERS 表中引用其他表的主键的外键。 结果集将有一行:下表显示了重要列。

PKTABLE_NAME PKCOLUMN_NAME FKTABLE_NAME FKCOLUMN_NAME KEY_SEQ
客户 CUSTID ORDERS CUSTID 1
#define TAB_LEN SQL_MAX_TABLE_NAME_LEN + 1  
#define COL_LEN SQL_MAX_COLUMN_NAME_LEN + 1  
  
LPSTR   szTable;              /* Table to display */  
  
UCHAR szPkTable[TAB_LEN];   /* Primary key table name */  
UCHAR szFkTable[TAB_LEN];   /* Foreign key table name */  
UCHAR szPkCol[COL_LEN];     /* Primary key column */  
UCHAR szFkCol[COL_LEN];     /* Foreign key column */  
  
SQLHSTMT      hstmt;  
SQLINTEGER    cbPkTable, cbPkCol, cbFkTable, cbFkCol, cbKeySeq;  
SQLSMALLINT   iKeySeq;  
SQLRETURN     retcode;  
  
// Bind the columns that describe the primary and foreign keys.  
// Ignore the table schema, name, and catalog for this example.  
  
SQLBindCol(hstmt, 3, SQL_C_CHAR, szPkTable, TAB_LEN, &cbPkTable);  
SQLBindCol(hstmt, 4, SQL_C_CHAR, szPkCol, COL_LEN, &cbPkCol);  
SQLBindCol(hstmt, 5, SQL_C_SSHORT, &iKeySeq, TAB_LEN, &cbKeySeq);  
SQLBindCol(hstmt, 7, SQL_C_CHAR, szFkTable, TAB_LEN, &cbFkTable);  
SQLBindCol(hstmt, 8, SQL_C_CHAR, szFkCol, COL_LEN, &cbFkCol);  
  
strcpy_s(szTable, sizeof(szTable), "ORDERS");  
  
/* Get the names of the columns in the primary key. */  
  
retcode = SQLPrimaryKeys(hstmt,  
         NULL, 0,             /* Catalog name */  
         NULL, 0,             /* Schema name */  
         szTable, SQL_NTS);   /* Table name */  
  
while ((retcode == SQL_SUCCESS) || (retcode == SQL SUCCESS_WITH_INFO)) {  
  
   /* Fetch and display the result set. This will be a list of the */  
   /* columns in the primary key of the ORDERS table. */  
  
   retcode = SQLFetch(hstmt);  
   if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)  
      fprintf(out, "Table: %s Column: %s Key Seq: %hd \n", szPkTable, szPkCol,  
      iKeySeq);  
}  
  
/* Close the cursor (the hstmt is still allocated). */  
  
SQLFreeStmt(hstmt, SQL_CLOSE);  
  
/* Get all the foreign keys that refer to ORDERS primary key.*/   
  
retcode = SQLForeignKeys(hstmt,  
         NULL, 0,            /* Primary catalog */  
         NULL, 0,            /* Primary schema */  
         szTable, SQL_NTS,   /* Primary table */  
         NULL, 0,            /* Foreign catalog */  
         NULL, 0,            /* Foreign schema */  
         NULL, 0);           /* Foreign table */  
  
while ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO)) {  
  
/* Fetch and display the result set. This will be all of the */  
/* foreign keys in other tables that refer to the ORDERS */  
/* primary key. */  
  
   retcode = SQLFetch(hstmt);  
   if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)  
      fprintf(out, "%-s ( %-s ) <-- %-s ( %-s )\n", szPkTable,  
               szPkCol, szFkTable, szFkCol);  
}  
  
/* Close the cursor (the hstmt is still allocated). */  
  
SQLFreeStmt(hstmt, SQL_CLOSE);  
  
/* Get all the foreign keys in the ORDERS table. */  
  
retcode = SQLForeignKeys(hstmt,  
         NULL, 0,             /* Primary catalog */  
         NULL, 0,             /* Primary schema */  
         NULL, 0,             /* Primary table */  
         NULL, 0,             /* Foreign catalog */  
         NULL, 0,             /* Foreign schema */  
         szTable, SQL_NTS);   /* Foreign table */  
  
while ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO)) {  
  
/* Fetch and display the result set. This will be all of the */  
/* primary keys in other tables that are referred to by foreign */  
/* keys in the ORDERS table. */  
  
   retcode = SQLFetch(hstmt);  
   if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)  
      fprintf(out, "%-s ( %-s )--> %-s ( %-s )\n", szFkTable, szFkCol, szPkTable, szPkCol);  
}  
  
/* Free the hstmt. */  
SQLFreeStmt(hstmt, SQL_DROP);  
有关以下方面的信息 请参阅
将缓冲区绑定到结果集中的列 SQLBindCol 函数
取消语句处理 SQLCancel 函数
以仅向前方向提取单行或数据块 SQLFetch 函数
提取数据块或滚动浏览结果集 SQLFetchScroll Function(SQLFetchScroll 函数)
返回主键的列 SQLPrimaryKeys 函数
返回表统计信息和索引 SQLStatistics 函数

另请参阅

ODBC API 参考
ODBC 头文件