如果使用占位符的查询使用非关联数组,PDO是否在意?

时间:2014-07-10 22:47:35

标签: php mysql pdo prepared-statement

我的应用程序中有一个查询,如下所示:

$stmt = db::db()->prepare('INSERT INTO t(a,b) VALUES :a,:b)');
$stmt->execute(array(1,2));

后来,我遇到了一个无关的错误,在查看这个脚本时,我问自己为什么以前有过这样的错误。我原以为我应该用

$stmt->execute(array('a'=>1,'b'=>2));

但是,它似乎有用吗?

是否可以使用带有预备语句的非关联数组,其中占位符是数组键而不是问号?

并不是说我会参与这种练习,但这让我很难过,我只需要知道。

谢谢

1 个答案:

答案 0 :(得分:0)

是PDO 关注,在这种情况下,准备不会失败,因为客户端向数据库服务器发送部分查询,  此查询必须完全减去数据,因此可以对其进行预处理。  然后,客户端一次或多次发送数据,然后服务器使用数据执行预处理的查询。

执行时应该引发以下异常:

{ "HY093",  "Invalid parameter number" }

如果您阅读执行函数的PDO源代码,您将看到以下引发此错误的代码:

if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(input_params),
            &param.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(&param, 0, sizeof(param));

            if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(input_params),
                        &param.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(&param, stmt, 1 TSRMLS_CC)) {
                if (param.parameter) {
                    zval_ptr_dtor(&param.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;
}
/* }}} */