Ошибка вставки с помощью SQLITE и PHP PDO — общая ошибка: 25 привязок или индекс столбца вне допустимого диапазона

Я пытаюсь вставить некоторые данные в свою базу данных, используя функцию PHP PDO в рамках Slim framework, но когда я публикую сообщения с помощью curl, я получаю следующую ошибку:

SQLSTATE[HY000]: общая ошибка: привязка 25 или индекс столбца вне допустимого диапазона

Используемая мной команда curl:

curl -i -X POST -H 'Content-Type: application/json' -d '{"category_name":"cat3",     "item_name":"test"}' http://localhost/api/add

Рассматриваемая функция PHP:

Функция ошибки

function addContent() {
    $request = \Slim\Slim::getInstance()->request();
    $content = json_decode($request->getBody());
    $sql = "insert into category (category_name) values (:category_name);
    insert into item (category_id,item_name) values 
    ((select category_id from category where category_name = :category_name2),     :item_name);";
    try {
        $db = getConnection();
        $stmt = $db->prepare($sql);
        $stmt->bindParam("category_name", $content->category_name);
        $stmt->bindParam("category_name2", $content->category_name);
        $stmt->bindParam("item_name", $content->item_name);
        $stmt->execute();
        $db = null;
        echo json_encode($content);
    } catch(PDOException $e) {
        echo '{"error":{"text":'. $e->getMessage() .'}}';
    }
}

SQL в основном добавляет новую категорию в таблицу категорий, а затем добавляет новый элемент в таблицу элементов, который ссылается на вновь созданную категорию. Если я запускаю запрос в sqlite, то кажется, что нужные строки добавляются просто отлично, запрос;

insert into category(category_name) values ('cat2');
insert into item (category_id,item_name) values
((select category_id from category where category_name = 'cat2'),'item3');

У меня есть что-то подобное, написанное для категорий, которые уже существуют, и, кажется, работает нормально;

Аналогичная рабочая функция

function addContent() {
    $request = \Slim\Slim::getInstance()->request();
    $content = json_decode($request->getBody());
    $sql = "insert into item (category_id,item_name) values
((select category_id from category where category_name = :category_name), :item_name);";
    try {
        $db = getConnection();
        $stmt = $db->prepare($sql);
        $stmt->bindParam("category_name", $content->category_name);
        $stmt->bindParam("item_name", $content->item_name);
        $stmt->execute();
        $db = null;
        echo json_encode($content);
    } catch(PDOException $e) {
        echo '{"error":{"text":'. $e->getMessage() .'}}';
    }
}

Почитав вокруг, я понял, что мне нужно установить две ссылки :category_name отдельно, поэтому у меня есть :category_name и :category_name2. В противном случае, насколько мне известно, это должно работать так, как ожидалось. Любые советы высоко ценится.

Рабочая функция предоставлена ​​ответами IMSoP и jeroen.

Теперь это работает по мере необходимости, хотя, возможно, это не самое красивое решение, но делает свою работу. Спасибо за совет, ребята.

function addContent() {
    $request = \Slim\Slim::getInstance()->request();
    $content = json_decode($request->getBody());
    $sql_category = "insert into category (category_name) values (:category_name);";
    $sql_item = "insert into item (category_id,item_name) values 
((select category_id from category where category_name = :category_name),     :item_name);";
    try {
        $db = getConnection();

        $stmt_category = $db->prepare($sql_category);
        $stmt_category->bindParam("category_name", $content->category_name);
        $stmt_category->execute();

        $stmt_item = $db->prepare($sql_item);
        $stmt_item->bindParam("category_name", $content->category_name);
        $stmt_item->bindParam("item_name", $content->item_name);
        $stmt_item->execute();

        $db = null;
        echo json_encode($content);
    } catch(PDOException $e) {
        echo '{"error":{"text":'. $e->getMessage() .'}}';
    }
}

person chrisdwheatley    schedule 13.03.2013    source источник


Ответы (2)


Строка SQL, которую вы пытаетесь подготовить, содержит 2 оператора SQL. Я не знаю точно, но, вероятно, SQLite (или драйвер PDO) не будет поддерживать это, поэтому будет подготовлен только один из них, то есть заполнители в другом не определены.

Попробуйте разделить его на два отдельных оператора, каждый из которых готовится и выполняется отдельно.

person IMSoP    schedule 13.03.2013
comment
Спасибо, мне удалось заставить это работать как требуется, см. дополнение к вопросу. - person chrisdwheatley; 14.03.2013

Проблема может заключаться в том, что PDO не может выполнять несколько операторов SQL в одном запросе. Чтобы увидеть, не в этом ли проблема, просто разделите запросы на разные вызовы.

Вы также можете проверить здесь, если система соответствует требованиям для выполнения нескольких запросов в PDO.

person jeroen    schedule 13.03.2013
comment
Судя по тегам, это SQLite, а не MySQL - person IMSoP; 14.03.2013
comment
@IMSoP Вы правы, ссылка / последний абзац не применима. - person jeroen; 14.03.2013