0

我遇到了使用 Yii 通过 odbc 连接到 sybase 的存储过程和多语句事务的问题。

为了隔离我在事务中运行存储过程时遇到的以下错误...

CDbCommand failed to execute the SQL statement: SQLSTATE[ZZZZZ]: <>: 7713 [Sybase][ODBC Driver][Adaptive Server Enterprise]Stored procedure 'myStoredProcedure' may be run only in unchained transaction mode. The 'SET CHAINED OFF' command will cause the current session to use unchained transaction mode. (SQLExecute[7713] at /builddir/build/BUILD/php-5.3.3/ext/pdo_odbc/odbc_stmt.c:254). The SQL statement executed was: exec myStoredProcedure 

我尝试了以下非常简单的测试:

$connection=Yii::app()->db;
$transaction = Yii::app()->db->beginTransaction();
$sql="select 'Tranchained'=@@tranchained";  //0=off, 1=on
$command=$connection->createCommand($sql);
error_log('Chained Mode On or Off ='.$command->queryScalar());
$transaction->commit();

错误日志显示 Chained Mode On 或 Off = 1,这意味着事务正在打开链接模式。这与我认为它应该做的相反。我还确认了链接模式在此事务之外已关闭,因此我确信是事务将其打开。

简单的解决方案是通过在事务中(在顶部)插入以下代码,添加一条 sql 语句来关闭事务内部的链式模式:

$sql='set chained off';
$command=$connection->createCommand($sql);
$command->execute();

这适用于我的简单示例。但是,当我在实际应用程序中使用它时它不起作用,因为我使用的是多语句事务,所以我收到以下错误:

CDbCommand failed to execute the SQL statement: SQLSTATE[ZZZZZ]: <>: 226 [Sybase][ODBC Driver][Adaptive Server Enterprise]SET CHAINED command not allowed within multi-statement transaction. (SQLExecute[226] at /builddir/build/BUILD/php-5.3.3/ext/pdo_odbc/odbc_stmt.c:254). The SQL statement executed was: set chained off 

我也试过:

$connection->setAutoCommit(false);

无济于事

4

1 回答 1

0

简单的解决方案。不要使用

Yii::app()->db->beginTransaction();

而是这样做,它实际上可以按预期工作和表现

$sql='begin transaction'; //or commit transaction, or rollback transaction
$command=$connection->createCommand($sql);
$command->execute();

可以按如下方式创建临时类(可能是一种更优雅的方法)。

class SybaseDb {

    public function beginTransaction() {
        $connection=Yii::app()->db;
        $sql='
            begin transaction 
        ';
        $command=$connection->createCommand($sql);
        $command->execute();        
    }

    public function rollBack() {
        $connection=Yii::app()->db;     
        $sql='
            rollback transaction 
        ';
        $command=$connection->createCommand($sql);
        $command->execute();            
    }

    public function commit() {
        $connection=Yii::app()->db; 
        $sql='
            commit transaction 
        ';
        $command=$connection->createCommand($sql);
        $command->execute();        
    }   

}
于 2013-01-08T16:48:25.943 回答