我的应用程序中有一个查询,如下所示:
$stmt = db::db()->prepare('INSERT INTO t(a,b) VALUES :a,:b)');
$stmt->execute(array(1,2));
后来,我遇到了一个无关的错误,在查看这个脚本时,我问自己为什么以前有过这样的错误。我原以为我应该用
$stmt->execute(array('a'=>1,'b'=>2));
但是,它似乎有用吗?
是否可以使用带有预备语句的非关联数组,其中占位符是数组键而不是问号?
并不是说我会参与这种练习,但这让我很难过,我只需要知道。
谢谢
答案 0 :(得分:0)
是PDO 关注,在这种情况下,准备不会失败,因为客户端向数据库服务器发送部分查询, 此查询必须完全减去数据,因此可以对其进行预处理。 然后,客户端一次或多次发送数据,然后服务器使用数据执行预处理的查询。
执行时应该引发以下异常:
{ "HY093", "Invalid parameter number" }
如果您阅读执行函数的PDO源代码,您将看到以下引发此错误的代码:
if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(input_params),
¶m.name, &str_length, &num_index, 0, NULL)) {
/* yes this is correct. we don't want to count the null byte. ask wez */
param.namelen = str_length - 1;
param.paramno = -1;
} else {
/* we're okay to be zero based here */
if (num_index < 0) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY093", NULL TSRMLS_CC);
RETURN_FALSE;
}
param.paramno = num_index;
}
我不确定它对你有用,所以我确保设置了PDO errormode属性。
您仍然必须小心,因为您必须处理我们传递给PDOStatement::execute()
方法的数组中元素的正确顺序。
execute()
完整功能
/* {{{ proto bool PDOStatement::execute([array $bound_input_params])
Execute a prepared statement, optionally binding parameters */
static PHP_METHOD(PDOStatement, execute)
{
zval *input_params = NULL;
int ret = 1;
PHP_STMT_GET_OBJ;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &input_params)) {
RETURN_FALSE;
}
PDO_STMT_CLEAR_ERR();
if (input_params) {
struct pdo_bound_param_data param;
zval **tmp;
uint str_length;
ulong num_index;
if (stmt->bound_params) {
zend_hash_destroy(stmt->bound_params);
FREE_HASHTABLE(stmt->bound_params);
stmt->bound_params = NULL;
}
zend_hash_internal_pointer_reset(Z_ARRVAL_P(input_params));
while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(input_params), (void*)&tmp)) {
memset(¶m, 0, sizeof(param));
if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(input_params),
¶m.name, &str_length, &num_index, 0, NULL)) {
/* yes this is correct. we don't want to count the null byte. ask wez */
param.namelen = str_length - 1;
param.paramno = -1;
} else {
/* we're okay to be zero based here */
if (num_index < 0) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY093", NULL TSRMLS_CC);
RETURN_FALSE;
}
param.paramno = num_index;
}
param.param_type = PDO_PARAM_STR;
MAKE_STD_ZVAL(param.parameter);
MAKE_COPY_ZVAL(tmp, param.parameter);
if (!really_register_bound_param(¶m, stmt, 1 TSRMLS_CC)) {
if (param.parameter) {
zval_ptr_dtor(¶m.parameter);
}
RETURN_FALSE;
}
zend_hash_move_forward(Z_ARRVAL_P(input_params));
}
}
if (PDO_PLACEHOLDER_NONE == stmt->supports_placeholders) {
/* handle the emulated parameter binding,
* stmt->active_query_string holds the query with binds expanded and
* quoted.
*/
ret = pdo_parse_params(stmt, stmt->query_string, stmt->query_stringlen,
&stmt->active_query_string, &stmt->active_query_stringlen TSRMLS_CC);
if (ret == 0) {
/* no changes were made */
stmt->active_query_string = stmt->query_string;
stmt->active_query_stringlen = stmt->query_stringlen;
ret = 1;
} else if (ret == -1) {
/* something broke */
PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
} else if (!dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_PRE TSRMLS_CC)) {
PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
if (stmt->methods->executer(stmt TSRMLS_CC)) {
if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
efree(stmt->active_query_string);
}
stmt->active_query_string = NULL;
if (!stmt->executed) {
/* this is the first execute */
if (stmt->dbh->alloc_own_columns && !stmt->columns) {
/* for "big boy" drivers, we need to allocate memory to fetch
* the results into, so lets do that now */
ret = pdo_stmt_describe_columns(stmt TSRMLS_CC);
}
stmt->executed = 1;
}
if (ret && !dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_POST TSRMLS_CC)) {
RETURN_FALSE;
}
RETURN_BOOL(ret);
}
if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
efree(stmt->active_query_string);
}
stmt->active_query_string = NULL;
PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
/* }}} */