3

CentOS6.2でPHP5.3.3、PostgreSQL 8.4.11、pgbouncer 1.3.4(sessionモード)を使用して、いくつかのSQLコマンドを実行し、PHPスクリプトで結果を取得しようとしています。

コマンドをスクリプトからpsqlプロンプトにコピーすると、コマンドは問題なく機能し、12行を返します。

ここに画像の説明を入力してください

しかし、スクリプトから実行すると、次のエラーが発生します。

SQLSTATE[42601]: Syntax error: 7 ERROR: cannot insert multiple commands into a prepared statement

何か助けてください?

以下は私の失敗したPHPコードです、私も$db->query()代わりに使用してみ$db->prepare/executeました:

try {
        $options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
        $db = new PDO(sprintf('pgsql:host=%s port=%u; dbname=%s',
                DBHOST, DBPORT, DBNAME), DBUSER, DBPASS, $options);

        $sth = $db->prepare("
            start transaction;
            create temporary table temp_ids (id varchar not null) on commit drop;
            insert into temp_ids (id)
                    select id
                    from pref_money
                    where yw = to_char(current_timestamp - interval '1 week', 'IYYY-IW')
                    order by money
                    desc limit 10;

            create temporary table temp_rids (rid integer not null) on commit drop;
            insert into temp_rids (rid)
                    select rid
                    from pref_cards
                    where stamp > now() - interval '1 day' and
                    id in (select id from temp_ids) and
                    bid = 'Мизер' and
                    trix > 0;

            SELECT r.rid, r.cards, to_char(r.stamp, 'DD.MM.YYYY HH24:MI') as day,
                    c.bid, c.trix, c.pos, c.money, c.last_ip, c.quit,
                    u.id, u.first_name, u.avatar, u.female, u.city, u.vip > CURRENT_DATE as vip
                    FROM pref_rounds r, pref_cards c, pref_users u
                    WHERE u.id = c.id and
                        r.rid = c.rid and
                        r.rid in (select rid from temp_rids)
                    order by rid, pos;
            commit;
        ");
        $sth->execute();
        while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
              # stuff a JSON object
        }
} catch (Exception $e) {
        exit('Database problem: ' . $e->getMessage());
}
4

2 に答える 2

3

これを試して、トランザクションを開始し、クエリを分割します。ユーザー入力から値を挿入しないため、クエリを準備する必要がなく、最後の 1 つの exec 以外の結果を期待していないため、問題ありません。最後のものでは、query() を使用できます。例外が発生した場合は、変更をロールバックできます。

<?php 
try {
    $options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
    $db = new PDO(sprintf('pgsql:host=%s port=%u; dbname=%s',
    DBHOST, DBPORT, DBNAME), DBUSER, DBPASS, $options);
    //Transaction
    $db->beginTransaction();

    $db->exec("create temporary table temp_ids (id varchar not null) on commit drop;");

    $db->exec("insert into temp_ids (id)
                    select id
                    from pref_money
                    where yw = to_char(current_timestamp - interval '1 week', 'IYYY-IW')
                    order by money
                    desc limit 10;");

    $db->exec("create temporary table temp_rids (rid integer not null) on commit drop;");

    $db->exec("insert into temp_rids (rid)
                    select rid
                    from pref_cards
                    where stamp > now() - interval '1 day' and
                    id in (select id from temp_ids) and
                    bid = 'Мизер' and
                    trix > 0;");
    //Commit changes before doing your select
    $db->commit();

    $sth = $db->query("SELECT r.rid, r.cards, to_char(r.stamp, 'DD.MM.YYYY HH24:MI') as day,
                    c.bid, c.trix, c.pos, c.money, c.last_ip, c.quit,
                    u.id, u.first_name, u.avatar, u.female, u.city, u.vip > CURRENT_DATE as vip
                    FROM pref_rounds r, pref_cards c, pref_users u
                    WHERE u.id = c.id and
                        r.rid = c.rid and
                        r.rid in (select rid from temp_rids)
                    order by rid, pos;");


    while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
        # stuff a JSON object
    }
} catch (Exception $e) {
    //Transaction rollback
    $db->rollback();
    exit('Database problem: ' . $e->getMessage());
}

?>
于 2012-06-13T08:42:00.540 に答える
2

メーリングリストに一時的なものを取り除くためのヒントがあります。テーブルとそれは私のために働く:

select r.rid, r.cards, to_char(r.stamp, 'DD.MM.YYYY HH24:MI') as day,
    c.bid, c.trix, c.pos, c.money, c.last_ip, c.quit,
    u.id, u.first_name, u.avatar, u.female, u.city, u.vip > CURRENT_DATE as vip
    from pref_rounds r, pref_cards c, pref_users u
    where u.id = c.id and
    r.rid = c.rid and
    r.rid in (
        select rid
            from pref_cards
            where stamp > CURRENT_TIMESTAMP - interval '1 day' and
            id in (
                select id
                    from pref_money
                    where yw = to_char(CURRENT_TIMESTAMP - interval '1 week', 'IYYY-IW')
                    order by money
                    desc limit 10) and
                   bid = 'Misere' and
                   trix > 0
    )
    order by r.rid, c.pos
于 2012-06-16T13:33:45.383 に答える