前提背景:
遇到了一个特别奇怪的问题,调用SQLBindParameter进行参数绑定是,最后一个参数交互的是绑定数据的长度,整数类型指针,随后我就传入了个局部遍历取地址传入,随后执行时程序说不定什么时候就莫名的段错误,最后查找文档和对这段代码进行调试,最后确定要传入的是全局变量,或当调用SQLExecute执行完SQL语句再释放,因为在调用 SQLExecute() 或 SQLExecDirect() 时,并且 StrLen_or_IndPtr (最后一个指针)指向 SQL_DATA_AT_EXEC 值时, 将使用 SQLPutData() 来发送数据。此参数称为执行数据参数。 以下红色标记,是对上述出现问题的准确回复。
参考文件:
DB2 通用数据库 iSeries 版 SQL 调用层接口(ODBC)
SQLBindParameter() 用来使 SQL 语句中的参数标记与应用程序变量相关联(绑定)。当调用SQLExecute() 或 SQLExecDirect() 时,将把数据从应用程序传送至 DBMS。在传送数据时,可能会发生数据转换。
还必须使用此函数来将应用程序存储器绑定到存储过程 CALL 语句的参数,该参数可以是输入参数、输出参数或输入输出参数。此函数本质上是 SQLSetParam() 的扩展。
语法
SQLRETURN SQLBindParameter(SQLHSTMT StatementHandle,
SQLSMALLINT ParameterNumber,
SQLSMALLINT InputOutputType,
SQLSMALLINT ValueType,
SQLSMALLINT ParameterType,
SQLINTEGER ColumnSize,
SQLSMALLINT DecimalDigits,
SQLPOINTER ParameterValuePtr,
SQLINTEGER BufferLength,
SQLINTEGER *StrLen_or_IndPtr);
函数自变量
表 22. SQLBindParameter 自变量
数据类型 | 自变量 | 使用 | 描述 |
---|---|---|---|
SQLHSTMT | StatementHandle | 输入 | 语句句柄 |
SQLSMALLINT | ParameterNumber | 输入 | 参数标记编号,此编号从 1 开始从左到右按顺序排序。 |
SQLSMALLINT | InputOutputType | 输入 | 参数的类型。IPD 的 SQL_DESC_PARAMETER_TYPE 字段的值也设置为此自变量。支持的类型包括:
|
SQLSMALLINT | ValueType | 输入 | 参数的 C 数据类型。支持下列类型:
指定 SQL_C_DEFAULT 将导致将数据由其缺省 C 数据类型转换为 ParameterType 指示的类型。 |
SQLSMALLINT | ParameterType | 输入 | 参数的 SQL 数据类型。 |
SQLINTEGER | ColumnSize | 输入 | 对应的参数标记的精度。如果ParameterType 指示:
|
SQLSMALLINT | DecimalDigits | 输入 | 相应参数的标度(如果ParameterType 是 SQL_DECIMAL 或 SQL_NUMERIC 的话)。如果 ParameterType 是 SQL_TYPE_TIMESTAMP,则这是时间戳记的字符表示法中小数点右边的位数(例如,yyyy-mm-dd hh:mm:ss.fff 的标度是 3)。 除了用于此处提到的 ParameterType 值之外,忽略 DecimalDigits。 |
SQLPOINTER | ParameterValuePtr | 输入(延迟)和/或输出(延迟) |
|
SQLINTEGER | BufferLength | 输入 | 不使用。 |
SQLINTEGER * | StrLen_or_IndPtr | 输入(延迟)和/或输出(延迟) | 如果这是输入或输入/输出参数: 这是指向一个位置的指针,(在执行语句时,)该位置包含存储在 ParameterValuePtr 处的参数标记值的长度。 要对参数标记指定空值,此存储器位置必须包含 SQL_NULL_DATA。 如果 ValueType 是 SQL_C_CHAR,则此存储位置必须包含存储在 ParameterValuePtr 处的数据的精确长度,或者,如果ParameterValuePtr 处的内容是以空终止的, 则必须包含 SQL_NTS。 如果 ValueType 指示 LOB 数据,则此存储位置必须包含存储在 ParameterValuePtr 处的数据的长度。 如果 ValueType 指示字符数据(显式指定,或使用 SQL_C_DEFAULT 隐式指定),并且此指针设置为空,则假定应用程序总是在ParameterValuePtr 中提供以空终止的字符串。这还暗示此参数标记永远不会具有空值。 在调用 SQLExecute() 或 SQLExecDirect() 时,并且 StrLen_or_IndPtr 指向 SQL_DATA_AT_EXEC 值时,将使用SQLPutData() 来发送数据。此参数称为执行数据参数。 |
用法
参数标记由 SQL 语句中的“?”字符表示,它用来指示语句中的一个位置,执行语句时,将在该位置替代应用程序提供的值。这个值是从应用程序变量获取的。
在执行 SQL 语句之前,应用程序必须将变量绑定到 SQL 语句中的每个参数标记。对于此函数,ParameterValuePtr 和 StrLen_or_IndPtr 是延迟自变量;在执行语句时,存储位置必须有效并且包含输入数据值。这意味着应该将 SQLExecDirect() 或SQLExecute() 调用与 SQLBindParameter() 调用置于同一个过程作用域中,或者,必须动态地分配或静态地或全局地声明这些存储位置。
参数标记是通过编号(ParameterNumber)引用的,并且是从 1 开始从左到右按顺序编号的。
此函数绑定的所有参数将一直有效,这将持续到使用 SQL_DROP 或 SQL_RESET_PARAMS 选项调用 SQLFreeStmt() 为止,或持续到对同一个参数编号ParameterNumber 再次调用 SQLBindParameter() 为止。
在执行 SQL 语句且处理结果之后,应用程序可能希望重新使用该语句句柄来执行另一个 SQL 语句。如果参数标记规格不同(参数数目、长度或类型),则应使用 SQL_RESET_PARAMS 来调用SQLFreeStmt() 以重设或清除参数绑定。
ValueType 给出的 C 缓冲区数据类型必须与 ParameterType 指示的 SQL 数据类型相兼容,否则会出错。
应用程序可以在 ParameterValuePtr 缓冲区中传送参数值,也可以通过调用一次或多次 SQLPutData() 来进行传送。在后一种情况下,这些参数是执行数据参数。应用程序通过将 SQL_DATA_AT_EXEC 值放入StrLen_or_IndPtr 缓冲区来将执行数据参数的情况通知 DB2 UDB CLI。它将 ParameterValuePtr 输入自变量设置成一个 32 位值,后续的SQLParamData() 调用将返回这个值,并且这个值可用来标识参数位置。
由于在执行语句之前不会对 ParameterValuePtr 和 StrLen_or_IndPtr 引用的变量中的数据进行验证,所以在调用SQLExecute() 或 SQLExecDirect() 之前不会检测或报告数据内容或格式错误。
SQLBindParameter() 在实质上是通过提供用于指定参数是输入、输入和输出或输出的方法来扩展 SQLSetParam() 函数的功能。要正确地处理存储过程的参数,此信息是必需的。
InputOutputType 自变量指定参数的类型。不调用过程的 SQL 语句中的所有参数都是输入参数。存储过程调用中的参数可以是输入、输入/输出或输出参数。虽然 DB2 存储过程自变量约定通常暗示所有过程自变量都是输入/输出自变量,但应用程序员仍可以选择在SQLBindParameter() 上更确切地指定输入或输出性质以遵循更严格的编码样式。并且,请注意,这些类型应该与使用 SQL CREATE PROCEDURE 语句注册存储过程时指定的参数类型一致。
- 如果应用程序不能确定过程调用中的参数的类型,则将 InputOutputType 设置为 SQL_PARAM_INPUT;如果数据源对该参数返回一个值,则 DB2 UDB CLI 将其废弃。
- 如果应用程序将一个参数标记为 SQL_PARAM_INPUT_OUTPUT 或 SQL_PARAM_OUTPUT,并且数据源没有返回值,DB2 UDB CLI 就会将StrLen_or_IndPtr 缓冲区设置为 SQL_NULL_DATA。
- 如果应用程序将参数标记为 SQL_PARAM_OUTPUT,则在处理 CALL 语句之后将参数的数据返回给应用程序。如果 ParameterValuePtr 和StrLen_or_IndPtr 自变量都是空指针,则 DB2 UDB CLI 废弃输出值。如果数据源没有对某个输出参数返回值,DB2 UDB CLI 就会将StrLen_or_IndPtr 缓冲区设置为 SQL_NULL_DATA。
- 对于此函数,ParameterValuePtr 和 StrLen_or_IndPtr 都是延迟自变量。对于 InputOutputType 设置为 SQL_PARAM_INPUT 或 SQL_PARAM_INPUT_OUTPUT 的情况,在执行语句时,存储位置必须有效并且包含输入数据值。这意味着应该将SQLExecDirect() 或 SQLExecute() 调用与 SQLBindParameter() 调用置于同一个过程作用域中,或者,必须动态地分配或静态地/全局地声明这些存储位置。
同样,如果 InputOutputType 设置为 SQL_PARAM_OUTPUT 或 SQL_PARAM_INPUT_OUTPUT,则在执行 CALL 语句之前,ParameterValuePtr 和 StrLen_or_IndPtr 缓冲区位置必须保持有效。
应用程序可以在 ParameterValuePtr 缓冲区中传送参数值,也可以通过调用一次或多次 SQLPutData() 来进行传送。在后一种情况下,这些参数是执行数据参数。应用程序通过将 SQL_DATA_AT_EXEC 值放入 StrLen_or_IndPtr 缓冲区来将执行数据参数的情况通知 DB2 UDB CLI。它将ParameterValuePtr 输入自变量设置成一个 32 位值,后续的 SQLParamData() 调用将返回这个值,并且这个值可用来标识参数位置。
当使用 SQLBindParameter() 来将应用程序变量绑定到存储过程的输出参数时,如果在内存中将 ParameterValuePtr 缓冲区相邻地放在StrLen_or_IndPtr 缓冲区之后,则 DB2 UDB CLI 能提供一定程度的性能增强。例如:
struct { SQLINTEGER StrLen_or_IndPtr;
SQLCHAR ParameterValuePtr[MAX_BUFFER];
} column;
返回码
- SQL_SUCCESS
- SQL_SUCCESS_WITH_INFO
- SQL_ERROR
- SQL_INVALID_HANDLE
若是进行ODBC或DB2进行数据库开发的话,建议参考此文档,对开发工作经会大有裨益:
http://publib.boulder.ibm.com/iseries/v5r2/ic2989/index.htm?info/cli/rzadpmst50.htm