0

PostgreSQLサーバーに機能があります

CREATE OR REPLACE FUNCTION edit_senti_meta_translation(_senti_id bigint, _meta_id bigint, _lang_code character, _meta_title character varying, _meta_note text)
  RETURNS boolean AS
$BODY$
BEGIN
    PERFORM
        senti.is_draft
    FROM
        senti, senti_meta
    WHERE
        senti.senti_id=_senti_id
    AND senti_meta.senti_id=senti.senti_id
    AND senti_meta.senti_id=_senti_id
    AND senti_meta.meta_id=_meta_id;
    IF FALSE THEN
        RETURN FALSE;
    END IF;
    BEGIN
        UPDATE senti_meta_translation
        SET meta_title=_meta_title, meta_note=_meta_note
        WHERE meta_id=_meta_id AND lang_code=_lang_code;
        IF FOUND THEN
            UPDATE senti_meta SET last_update=now() WHERE senti_id=_senti_id AND meta_id=_meta_id;
            RETURN TRUE;
        ELSE
            RETURN FALSE;
        END IF;
    END;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

さて、pgadmin3で試してみると機能しており、この関数を呼び出すとレコードが更新されました(期待どおりに100%機能します)。

SELECT edit_senti_meta_translation(1, 41, 'eng', 'a', 'a');

しかし、PHP(PDO Driver)を使用して関数を呼び出そうとすると、結果はtrueまたはfalseになりますが、UPDATEが実行されておらず、レコードが更新されていません。

$stmt = Database::getInstance()->prepare('SELECT * FROM edit_senti_meta_translation(:senti_id, :meta_id, :lang_code, :meta_title, :meta_note);');
$stmt->bindParam(':senti_id', $senti_id, PDO::PARAM_INT);
$stmt->bindParam(':meta_id', $meta_id, PDO::PARAM_INT);
$stmt->bindParam(':lang_code', $lang_code, PDO::PARAM_STR);
$stmt->bindParam(':meta_title', $meta_title, PDO::PARAM_STR);
$stmt->bindParam(':meta_note', $meta_note, PDO::PARAM_STR);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
return $stmt->fetchColumn(0);

PHPコードの最初の行を変更しても

$stmt = Database::getInstance()->prepare("SELECT edit_senti_meta_translation(1, 41, 'eng', 'a', 'a');");

結果(true / false)が表示されますが、レコードは更新されません。これは私をとても混乱させます

参考までに、私はPostgreSQL8.4を使用しています

混乱するのは、pgadmin3で関数を直接呼び出すと、レコードが更新された状態で正しい戻り値が返されるのですが、PHP(PDO)から呼び出すと、戻り値だけが返されますが、レコードは更新されません。

4

1 に答える 1

1

さて、問題に苦労した後、@dmirkitanovはなぜこれが起こるのかという考えで返信します。

たとえば、このコードがトランザクションで実行され、その後にコミットがない場合、トランザクションに関連している可能性があります

PDOシングルトンクラスで、プロジェクトの一部が新しい行を追加していることに気付きました。*コメントされたコード行を参照してください

<?php

include('config.database.php');

class Database {

    protected static $instance = null;

    final private function __construct() {}
    final private function __destruct() {
        //self::$instance->commit();
        self::$instance = null;
    }

    final private function __clone() {}

    public static function getInstance() {
        if (self::$instance === null) {
            try {
                self::$instance = new PDO(
                    'pgsql:host='   . DatabaseConfig::HOST . 
                    ';port='        . DatabaseConfig::PORT . 
                    ';dbname='      . DatabaseConfig::DBNAME . 
                    ';user='        . DatabaseConfig::USER . 
                    ';password='    . DatabaseConfig::PASSWORD
                );
                self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                self::$instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
                //self::$instance->beginTransaction();
            } catch (PDOException $e) {
                self::$instance->rollBack();
                die('Database connection could not be established.');
            }
        }

        return self::$instance;
    }
    public static function __callStatic($method, $args) {
        return call_user_func_array(array(self::instance(), $method), $args);
    }
}
?>

ご覧のとおり、beginTransaction()はに設定されていますがgetInstance()commit()はに設定されています__destruct()

于 2013-02-02T15:04:19.113 に答える