Php PDO是否关心占位符查询是否使用非关联数组?

Php PDO是否关心占位符查询是否使用非关联数组?,php,mysql,pdo,prepared-statement,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)); 但是,它似乎有效吗 在占位符是数组键而不是问号的情况下,可以将非关联数组

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

$stmt = db::db()->prepare('INSERT INTO t(a,b) VALUES :a,:b)');
$stmt->execute(array(1,2));
后来,我遇到了一个不相关的错误,当我回顾这个脚本时,我问自己为什么它以前能工作。我本以为我应该用

$stmt->execute(array('a'=>1,'b'=>2));
但是,它似乎有效吗

在占位符是数组键而不是问号的情况下,可以将非关联数组与准备好的语句一起使用吗

并不是说我会参加这个练习,但这让我感到困惑,我只需要知道


谢谢

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

但是,执行时应引发以下异常:

{ "HY093",  "Invalid parameter number" }
如果您阅读execute函数的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;
}

@ArtisticPhoenix让我完全惊讶的是,它似乎在任何一种情况下都起作用。我认为它只在执行绑定时起作用,即名称(显然在这种情况下它不是数组)。否则,它将接受命令,并退回到?占位符类型,可能有效,但如果它们的顺序不正确,则会出现问题。@ArtisiticPhoenix。我想是的。这太出乎意料了,我想我的代码一定被修改了,因为它以前不可能工作。哦,好吧。。。至少我知道。我从不使用?和方式进行查询,现在也很少编写实际的查询,主要是使用ORM.Hm。那是PDO的代码吗?因此,您需要删除一个数组定义。
/* {{{ 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;
}
/* }}} */