一致性
推出版本:ODBC 1.0 标准合规:ODBC
总结
SQLForeignKey 可以返回:
指定表中外键的列表(指定表中指向其他表中主键的列)。
指代指定表中主键的其他表中的外键列表。
驱动程序将每个列表作为指定语句的结果集返回。
Syntax
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);
Arguments
StatementHandle
[输入]语句句柄。
PKCatalogName
[输入]主键表目录名称。 如果驱动程序支持某些表的目录,但不支持其他表,例如当驱动程序从不同的数据库管理系统检索数据时,空字符串(“”)表示那些没有目录的表。
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
[输入]外键表目录名称。 如果驱动程序支持某些表的目录,但不支持其他表,例如当驱动程序从不同的数据库管理系统检索数据时,空字符串(“”)表示那些没有目录的表。
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 的字元长度。
Returns
SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_STILL_EXECUTING、SQL_ERROR或SQL_INVALID_HANDLE。
Diagnostics
当 SQLForeignKeys 返回 SQL_ERROR 或 SQL_SUCCESS_WITH_INFO 时,可以通过调用 SQLGetDiagRec 获得关联的 SQLSTATE 值,Handle 为 SQL_HANDLE_STMT,Handle 为 StatementHandle。 下表列出了 SQLForeignKeys 通常返回的SQLSTATE值,并在该函数的上下文中解释了每个值;“(DM)” 符号位于驱动程序管理器返回的 SQLSTATE 描述之前。 除非另有说明,否则与每个 SQLSTATE 值关联的返回代码SQL_ERROR。
| SQLSTATE | Error | Description |
|---|---|---|
| 01000 | 常规警告 | 特定于驱动程序的信息性消息。 (函数返回SQL_SUCCESS_WITH_INFO。) |
| 08S01 | 通信链接失败 | 驱动程序与驱动程序连接到的数据源之间的通信链接在函数完成处理之前失败。 |
| 24000 | 游标状态无效 |
StatementHandle 上打开了一个光标,调用了 SQLFetch 或 SQLFetchScroll。 如果 SQLFetch 或 SQLFetchScroll 未返回SQL_NO_DATA,并且如果 SQLFetch 或 SQLFetchScroll 返回SQL_NO_DATA,驱动程序将返回此错误。 StatementHandle 上开着光标,但未调用 SQLFetch 或 SQLFetchScroll。 |
| 40001 | 序列化失败 | 由于资源死锁与另一个事务,事务已回滚。 |
| 40003 | 语句完成未知 | 执行此函数期间关联的连接失败,无法确定事务的状态。 |
| HY000 | 常规错误 | 发生错误:没有特定的 SQLSTATE,也没有定义特定于实现的 SQLSTATE。 *MessageText 缓冲区中 SQLGetDiagRec 返回的错误消息描述错误及其原因。 |
| HY001 | 内存分配错误 | 驱动程序无法分配支持执行或完成函数所需的内存。 |
| HY008 | 操作已取消 | 为 StatementHandle 启用了异步处理。 函数被调用后,在执行完成前,先在 StatementHandle 上调用 SQLCancel 或 SQLCancelHandle,然后在 StatementHandle 上再次调用该函数。 调用了函数,在完成执行之前,SQLCancel 或 SQLCancelHandle 从多线程应用程序中的不同线程调用 StatementHandle。 |
| HY009 | 无效使用 null 指针 | (DM) 参数PKTableName 和 FKTableName 都是空指针。 SQL_ATTR_METADATA_ID语句属性被设置为 SQL_TRUE,FKCatalogName 或 PKCatalogName 参数是空指针,SQL_CATALOG_NAME InfoType 返回支持目录名称。 (DM) SQL_ATTR_METADATA_ID语句属性设置为SQL_TRUE,且 FKSchemaName、 PKSchemaName、 FKTableName或 PKTableName 参数为空指针。 |
| HY010 | 函数序列错误 | (DM) 为与 StatementHandle 关联的连接句柄调用异步执行函数。 当调用SQLForeignKeys函数时,该异步函数仍在执行。 (DM) 为 StatementHandle 调用了 SQLExecute、SQLExecDirect 或 SQLMoreResults,并返回了SQL_PARAM_DATA_AVAILABLE。 在检索所有流式处理参数的数据之前调用此函数。 (DM) 为 StatementHandle 调用异步执行函数(而不是此函数),并在调用此函数时仍在执行。 (DM) 为 StatementHandle 调用了 SQLExecute、SQLExecDirect、SQLBulkOperations 或 SQLSetPos,并返回了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 返回表中指定的外键,这些外 键指向 *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列(备注)之外的其他列。 应用程序应从结果集的末尾倒计时,而不是指定显式序号位置来访问特定于驱动程序的列。 有关详细信息,请参阅 目录函数返回的数据。
| 列名称 | 列号 | 数据类型 | 注释 |
|---|---|---|---|
| PKTABLE_CAT(ODBC 1.0) | 1 | Varchar | 主键表目录名称;如果不适用于数据源,则使用NULL。 如果驱动程序支持某些表的目录,但不支持其他表,例如当驱动程序从不同数据库管理系统检索数据时,对于没有目录的表,驱动程序会返回一个空字符串(“”)。 |
| PKTABLE_SCHEM(ODBC 1.0) | 2 | Varchar | 主键表模式名称;如果不适用于数据源,则使用NULL。 如果驱动程序支持某些表的模式,而不支持其他表,例如当驱动程序从不同数据库管理系统检索数据时,对于没有模式的表,驱动程序会返回一个空字符串(“”)。 |
| PKTABLE_NAME(ODBC 1.0) | 3 | Varchar 非 NULL | 主键表名称。 |
| PKCOLUMN_NAME(ODBC 1.0) | 4 | Varchar 非 NULL | 主键列名。 驱动程序返回一个没有名称的列的空字符串。 |
| FKTABLE_CAT(ODBC 1.0) | 5 | Varchar | 外键表目录名称;如果不适用于数据源,则使用NULL。 如果驱动程序支持某些表的目录,但不支持其他表,例如当驱动程序从不同数据库管理系统检索数据时,对于没有目录的表,驱动程序会返回一个空字符串(“”)。 |
| FKTABLE_SCHEM(ODBC 1.0) | 6 | Varchar | 外键表模式名称;如果不适用于数据源,则使用NULL。 如果驱动程序支持某些表的模式,而不支持其他表,例如当驱动程序从不同数据库管理系统检索数据时,对于没有模式的表,驱动程序会返回一个空字符串(“”)。 |
| 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。
| 订单 | 线路 | 客户 |
|---|---|---|
| 命令编号 | 命令编号 | 卡斯蒂德 |
| 卡斯蒂德 | 线路 | NAME |
| 开业日期 | 帕蒂德 | 地址 |
| 销售员 | 数量 | 电话 |
| STATUS |
在订单表中,CUSTID标识了销售对象的客户。 这是一个外键,在 CUSTOMERS 表中指向 CUSTID。
在LINES表中,ORDERID标识该条目关联的销售订单。 它是一个外键,在 ORDERS 表中指向 ORDERID。
本示例调用 SQLPrimaryKeys 获取 ORDERS 表的主键。 结果集将有一行;有效列如下表所示。
| TABLE_NAME | COLUMN_NAME | KEY_SEQ |
|---|---|---|
| 订单 | 命令编号 | 1 |
接下来,示例调用 SQLForeignKeys 获取其他表中引用 ORDERS 表主键的外键。 结果集将有一行;有效列如下表所示。
| PKTABLE_NAME | PKCOLUMN_NAME | FKTABLE_NAME | FKCOLUMN_NAME | KEY_SEQ |
|---|---|---|---|---|
| 订单 | 卡斯蒂德 | 线路 | 卡斯蒂德 | 1 |
最后,示例调用 SQLForeignKeys 获取 ORDERS 表中指向其他表主键的外键。 结果集将有一行;有效列如下表所示。
| PKTABLE_NAME | PKCOLUMN_NAME | FKTABLE_NAME | FKCOLUMN_NAME | KEY_SEQ |
|---|---|---|---|---|
| 客户 | 卡斯蒂德 | 订单 | 卡斯蒂德 | 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 函数 |
| 返回主键的列 | SQLPrimaryKeys 函数 |
| 返回表格统计和索引 | SQLStatistics 函数 |