1 参数绑定API
执行参数化查询,需要将语句中各个参数对应的变量缓存,与Statement句柄实现绑定。
用于绑定参数的ODBC API函数:
SQLRETURN SQLBindParameter(
SQLHSTMT StatementHandle, // statement句柄
SQLUSMALLINT ParameterNumber, // 参数位于语句中的序号,最小为1
SQLSMALLINT InputOutputType, // 入参/出参类型标识[1]
SQLSMALLINT ValueType, // 对应的C数据类型标识[2]
SQLSMALLINT ParameterType, // 对应的SQL数据类型标识[2]
SQLULEN ColumnSize, // 对应字段长度
SQLSMALLINT DecimalDigits, // 如果是浮点数,则对应字段精度
SQLPOINTER ParameterValuePtr, // 参数缓存
SQLLEN BufferLength, // 参数缓存字节数
SQLLEN * StrLen_or_IndPtr); // 用于表示字符串长度或NULL值的标识[3]
[1] 出参/入参标识:SQL_PARAM_INPUT,SQL_PARAM_OUTPUT,SQL_PARAM_INPUT_OUTPUT
ODBC 3.8后引入SQL_PARAM_INPUT_OUTPUT_STREAM和SQL_PARAM_OUTPUT_STREAM,
用于绑定时不指定数据长度,直到使用SQLGetData时,根据指定的缓存大小获取数据。
[2] ODBC数据类型标识:
SQL_CHAR,SQL_VARCHAR,SQL_LONGVARCHAR SQL_C_CHAR
SQL_WCHAR, SQL_WVARCHAR, SQL_WLONGVARCHAR SQL_C_WCHAR
----------------------------------------------------------------------------
SQL_DECIMAL,SQL_NUMERIC SQL_C_NUMERIC
SQL_BIGINT,SQL_INTEGER,SQL_SMALLINT, SQL_C_STINYINT,SQL_C_UTINYINT,
SQL_REAL,SQL_FLOAT,SQL_DOUBLE SQL_C_SSHORT,SQL_C_USHORT,
SQL_C_SLONG,SQL_C_ULONG,
SQL_C_SBIGINT,SQL_C_UBIGINT,
SQL_C_FLOAT,SQL_C_DOUBLE
----------------------------------------------------------------------------
SQL_TYPE_DATE SQL_C_TYPE_DATE
SQL_TYPE_TIME SQL_C_TYPE_TIME
SQL_TYPE_TIMESTAMP SQL_C_TYPE_TIMESTAMP
----------------------------------------------------------------------------
SQL_BINARY,SQL_VARBINARY,SQL_LONGVARBINARY SQL_C_BINARY
[3] StrLen_or_IndPtr: 用于表示ParameterValuePtr指向的缓存数据,
如果是字符串,则表示字符串有效字符数(或SQL_NTS表示NULL结尾)
如果字段值是NULL,则设置为SQL_NULL_DATA。
对于入参,如果输入值非NULL且不是字符串,则可输入NULL。
2 示例,执行参数化查询
void ExecuteParameterizedStatement(Statement hStmt)
{
//const char * pszStmtCreate
// = "CREATE TABLE test.my_table(name varchar(20), age numeric(8))";
const char * pszStmtInsert = "INSERT INTO test.my_table VALUES(?, ?)";
SQLRETURN ret = SQL_SUCCESS;
ret = SQLPrepare(hStmt, pszStmtInsert, SQL_NTS);
char szName[32];
int iAge;
SQLlEN ind_name = SQL_NTS;
ret = SQLBindParameter(
hStmt, SQL_PARAM_INPUT,
SQL_C_CHAR, SQL_VARCHAR, 20, 0,
(SQLPOINTER)szName, 32, &ind_name);
ret = SQLBindParameter(
hStmt, SQL_PARAM_INPUT,
SQL_C_SLONG, SQL_NUMERIC, 8, 0,
(SQLPOINTER)&iAge, sizeof(int), NULL);
// 向表中插入两条数据
strcpy(szName, "Michael");
iAge = 12;
ret = SQLExecute(hStmt);
strcpy(szName, "David");
iAge = 14;
ret = SQLExecute(hStmt);
}