预处理语句是一种参数化查询。查询使用问号 (?
) 或美元符号 ($1
) 来指示查询的参数,从而进行准备。然后,可以将值绑定到这些参数,之后即可使用这些参数执行预处理语句。单个查询可以只准备一次,然后执行多次。
预处理语句的用途包括:
- 轻松为函数提供参数,同时避免字符串拼接/SQL 注入攻击。
- 加速将使用不同参数多次执行的查询。
DuckDB 在 C API 中通过 duckdb_prepare
方法支持预处理语句。duckdb_bind
系列函数用于为后续使用 duckdb_execute_prepared
执行预处理语句提供值。完成预处理语句后,可以使用 duckdb_destroy_prepare
方法进行清理。
示例
duckdb_prepared_statement stmt;
duckdb_result result;
if (duckdb_prepare(con, "INSERT INTO integers VALUES ($1, $2)", &stmt) == DuckDBError) {
// handle error
}
duckdb_bind_int32(stmt, 1, 42); // the parameter index starts counting at 1!
duckdb_bind_int32(stmt, 2, 43);
// NULL as second parameter means no result set is requested
duckdb_execute_prepared(stmt, NULL);
duckdb_destroy_prepare(&stmt);
// we can also query result sets using prepared statements
if (duckdb_prepare(con, "SELECT * FROM integers WHERE i = ?", &stmt) == DuckDBError) {
// handle error
}
duckdb_bind_int32(stmt, 1, 42);
duckdb_execute_prepared(stmt, &result);
// do something with result
// clean up
duckdb_destroy_result(&result);
duckdb_destroy_prepare(&stmt);
调用 duckdb_prepare
后,可以使用 duckdb_nparams
和 duckdb_param_type
检查预处理语句参数。如果准备失败,可以通过 duckdb_prepare_error
获取错误信息。
不需要 duckdb_bind
系列函数与预处理语句参数类型完全匹配。值将根据需要自动转换为所需类型。例如,对 DUCKDB_TYPE_INTEGER
类型的参数调用 duckdb_bind_int8
将按预期工作。
警告:不要使用预处理语句向 DuckDB 插入大量数据。建议改用 追加器 (Appender)。
API参考概览
duckdb_state duckdb_prepare(duckdb_connection connection, const char *query, duckdb_prepared_statement *out_prepared_statement);
void duckdb_destroy_prepare(duckdb_prepared_statement *prepared_statement);
const char *duckdb_prepare_error(duckdb_prepared_statement prepared_statement);
idx_t duckdb_nparams(duckdb_prepared_statement prepared_statement);
const char *duckdb_parameter_name(duckdb_prepared_statement prepared_statement, idx_t index);
duckdb_type duckdb_param_type(duckdb_prepared_statement prepared_statement, idx_t param_idx);
duckdb_logical_type duckdb_param_logical_type(duckdb_prepared_statement prepared_statement, idx_t param_idx);
duckdb_state duckdb_clear_bindings(duckdb_prepared_statement prepared_statement);
duckdb_statement_type duckdb_prepared_statement_type(duckdb_prepared_statement statement);
duckdb_prepare
从查询创建预处理语句对象。
请注意,调用 duckdb_prepare
后,即使准备失败,也应始终使用 duckdb_destroy_prepare
销毁预处理语句。
如果准备失败,可以调用 duckdb_prepare_error
获取失败原因。
语法
duckdb_state duckdb_prepare(
duckdb_connection connection,
const char *query,
duckdb_prepared_statement *out_prepared_statement
);
参数
connection
:连接对象query
:要准备的 SQL 查询out_prepared_statement
:结果预处理语句对象
返回值
成功时返回 DuckDBSuccess
,失败时返回 DuckDBError
。
duckdb_destroy_prepare
关闭预处理语句并释放为该语句分配的所有内存。
语法
void duckdb_destroy_prepare(
duckdb_prepared_statement *prepared_statement
);
参数
prepared_statement
:要销毁的预处理语句。
duckdb_prepare_error
返回与给定预处理语句关联的错误消息。如果预处理语句没有错误消息,则返回 nullptr
。
错误消息不应被释放。它将在调用 duckdb_destroy_prepare
时被释放。
语法
const char *duckdb_prepare_error(
duckdb_prepared_statement prepared_statement
);
参数
prepared_statement
:要获取错误的预处理语句。
返回值
错误消息,如果没有则为 nullptr
。
duckdb_nparams
返回可提供给给定预处理语句的参数数量。
如果查询未成功准备,则返回 0。
语法
idx_t duckdb_nparams(
duckdb_prepared_statement prepared_statement
);
参数
prepared_statement
:要获取参数数量的预处理语句。
duckdb_parameter_name
返回用于标识参数的名称。返回的字符串应使用 duckdb_free
释放。
如果索引超出提供的预处理语句的范围,则返回 NULL。
语法
const char *duckdb_parameter_name(
duckdb_prepared_statement prepared_statement,
idx_t index
);
参数
prepared_statement
:要获取参数名称的预处理语句。
duckdb_param_type
返回给定索引处参数的参数类型。
如果参数索引超出范围或语句未成功准备,则返回 DUCKDB_TYPE_INVALID
。
语法
duckdb_type duckdb_param_type(
duckdb_prepared_statement prepared_statement,
idx_t param_idx
);
参数
prepared_statement
:预处理语句。param_idx
:参数索引。
返回值
参数类型
duckdb_param_logical_type
返回给定索引处参数的逻辑类型。
如果参数索引超出范围或语句未成功准备,则返回 nullptr
。
此调用的返回类型应使用 duckdb_destroy_logical_type
销毁。
语法
duckdb_logical_type duckdb_param_logical_type(
duckdb_prepared_statement prepared_statement,
idx_t param_idx
);
参数
prepared_statement
:预处理语句。param_idx
:参数索引。
返回值
参数的逻辑类型
duckdb_clear_bindings
清除绑定到预处理语句的参数。
语法
duckdb_state duckdb_clear_bindings(
duckdb_prepared_statement prepared_statement
);
duckdb_prepared_statement_type
返回要执行的语句的语句类型
语法
duckdb_statement_type duckdb_prepared_statement_type(
duckdb_prepared_statement statement
);
参数
statement
:预处理语句。
返回值
duckdb_statement_type 值或 DUCKDB_STATEMENT_TYPE_INVALID