触发器未被Yii应用程序激活

时间:2012-10-29 18:40:19

标签: php mysql pdo yii

大家好,StackOverflow中的每个人,我都是这个网站的粉丝,帮助我摆脱了无数的困境。但是这次我似乎没有在这里或其他任何地方找到答案,我的问题是:

我正在开发一个Yii框架应用程序来处理数据库中的数据,保持一致性和一切。基本上,我正在创建一个用于操纵数据库信息的界面。我正在使用MySQL 5.0(预定更新到5.5)和InnoDB。

我的开发工作将支持已经存在的架构(我将其称为 main ),这有几个设计问题。我们的目标是用一个新的,正确设计的模式替换旧模式(我称之为阴影)。但与此同时,我们正在尝试将新模式实现为主模式的影子模式,并通过触发器保持变化一致。

对影子架构进行了所有重要更改,影子架构使用触发器将其反映到主架构。两个模式都托管在同一个服务器中,并且只要通过命令行客户端或使用MySQL Workbench进行更改,触发器就能很好地反映从shadow到main的数据更改,但每当我使用我的Yii应用程序进行更改以隐藏数据时......更改仅对影子架构进行,而不是触发 - 反映到主架构。

这是 shadow.tbl_device 描述并触发DDL:

mysql> use shadow;
mysql> describe tbl_device;
+--------------+-------------+------+-----+-------------------+-----------------------------+
| Field        | Type        | Null | Key | Default           | Extra                       |
+--------------+-------------+------+-----+-------------------+-----------------------------+
| Id           | int(11)     | NO   | PRI | NULL              | auto_increment              |
| SerialNumber | varchar(40) | NO   |     | NULL              |                             |
| State        | varchar(20) | NO   | MUL | Recién Llegado    |                             |
| ProviderId   | int(11)     | NO   | MUL | NULL              |                             |
| OwnerId      | int(11)     | NO   | MUL | NULL              |                             |
| ProfileId    | int(11)     | YES  | MUL | NULL              |                             |
| ChipId       | int(11)     | YES  | UNI | NULL              |                             |
| IMEI         | varchar(15) | YES  |     | NULL              |                             |
| ModelNumber  | varchar(20) | YES  |     | NULL              |                             |
| FirstUsed    | date        | YES  |     | NULL              |                             |
| Brand        | varchar(45) | NO   | MUL | No Definida       |                             |
| Agreement    | varchar(20) | NO   | MUL | No Establecido    |                             |
| LastUpdated  | timestamp   | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+--------------+-------------+------+-----+-------------------+-----------------------------+
13 rows in set (0.01 sec)

-- Trigger DDL Statements

USE `shadow`$$

CREATE
DEFINER=`root`@`localhost`
TRIGGER `shadow`.`trg_device_after_insert_produce_location_and_register_device`
AFTER INSERT ON `shadow`.`tbl_device`
FOR EACH ROW
BEGIN
    DECLARE NumCel VARCHAR(10) DEFAULT NULL;
    INSERT INTO tbl_location(DeviceId) values (New.Id);
    IF New.ChipId IS NOT NULL THEN
        SELECT CONCAT(AreaCode,Phone) INTO NumCel FROM tbl_chip WHERE Id = New.ChipId;
    END IF;

    IF New.Brand = 'Navcel' THEN
        INSERT INTO navcel.detalle_aplicacion(apId, pdRadioId, adActivo) values (1,CAST(New.SerialNumber as UNSIGNED), 1);
    END IF;
    IF New.Brand = 'Calamp' Then
        INSERT INTO main.equipos(eqId,eqNumCel,shadowDeviceId) values (CONV(SUBSTRING(New.SerialNumber,-6),16,10),NumCel,New.Id);
    ELSE
        INSERT INTO main.equipos(eqId,eqNumCel,shadowDeviceId) values (CAST(New.SerialNumber as UNSIGNED),NumCel,New.Id);
    END IF;
END$$

CREATE
DEFINER=`root`@`localhost`
TRIGGER `shadow`.`trg_device_after_update_reflect_changes`
AFTER UPDATE ON `shadow`.`tbl_device`
FOR EACH ROW
BEGIN
    DECLARE acuerdo TINYINT(4);
    DECLARE NumCel VARCHAR(10);
    DECLARE eqIdToUpdate INT;
    IF New.LastUpdated <> Old.LastUpdated THEN
        /* UPDATING THE REFLECTION OF THIS DEVICE IN THE main SCHEMA */
        IF New.Agreement = 'Renta' THEN set acuerdo := 1;
            ELSEIF New.Agreement = 'Venta' THEN set acuerdo := 2;
            ELSEIF New.Agreement = 'Prestamo' THEN set acuerdo := 3;
            ELSE set acuerdo := 0;
        END IF;
        IF New.ChipId IS NULL THEN 
            SET NumCel = NULL;
        ELSE 
            Select CONCAT(AreaCode,Phone) INTO NumCel FROM tbl_chip WHERE Id = New.ChipId;
        END IF;
        UPDATE main.equipos SET 
            eqId := New.SerialNumber,
            eqInstalado := 1,
            eqAcuerdo := acuerdo,
            eqNumCel := NumCel
        WHERE shadowDeviceId = New.id;
    END IF;
END$$

DDL中的触发器是用于反映对main的更改的触发器,这里是 main.equipos 描述(当前它不使用触发器):

+-----------------------+------------------+------+-----+---------+-------+
| Field                 | Type             | Null | Key | Default | Extra |
+-----------------------+------------------+------+-----+---------+-------+
| eqId                  | int(10) unsigned | NO   | PRI | 0       |       |
| shadowDeviceId        | int(11)          | YES  | UNI | NULL    |       |
| eqNumCel              | varchar(20)      | YES  |     | NULL    |       |
| stId                  | int(10) unsigned | NO   |     | 0       |       |
| TIPO_EQUIPOS_tpId     | int(10) unsigned | YES  |     | NULL    |       |
| eqNombre              | varchar(100)     | YES  |     | NULL    |       |
| eqNUI                 | varchar(50)      | YES  |     | NULL    |       |
| eqModelo              | varchar(20)      | YES  |     | NULL    |       |
| eqPlacas              | varchar(20)      | YES  |     | NULL    |       |
| eqLatitud             | decimal(9,6)     | YES  |     | NULL    |       |
| eqLongitud            | decimal(9,6)     | YES  |     | NULL    |       |
| eqAltitud             | float            | YES  |     | NULL    |       |
| eqSatelite            | varchar(20)      | YES  |     | NULL    |       |
| eqFechaActEq          | datetime         | YES  |     | NULL    |       |
| eqFechaActSer         | datetime         | YES  |     | NULL    |       |
| eqNivelGPRS           | float            | YES  |     | NULL    |       |
| eqIcono               | varchar(200)     | YES  |     | NULL    |       |
| eqTiempoRep           | datetime         | YES  |     | NULL    |       |
| eqVersion             | varchar(20)      | YES  |     | NULL    |       |
| eqLatDinGeo           | float            | YES  |     | NULL    |       |
| eqLonDinGeo           | float            | YES  |     | NULL    |       |
| eqTiempoGeo           | datetime         | YES  |     | NULL    |       |
| eqNumEconomico        | varchar(20)      | YES  |     | NULL    |       |
| eqNumPedido           | varchar(20)      | YES  |     | NULL    |       |
| eqVelocidad           | int(10)          | YES  |     | NULL    |       |
| eqNumSerie            | varchar(45)      | YES  |     |         |       |
| EsGeocercaId          | int(10) unsigned | YES  |     | NULL    |       |
| eqPuntoCercano        | int(10)          | NO   |     | 1       |       |
| eqDistanciaCercano    | float            | NO   |     | 0       |       |
| eqIconoActual         | varchar(100)     | NO   |     | 0       |       |
| eqStatusDBS           | varchar(45)      | YES  |     |         |       |
| eqTieneDBS            | int(1)           | NO   |     | 1       |       |
| eqFechaDBS            | datetime         | YES  |     | NULL    |       |
| eqEnAlarma            | tinyint(1)       | NO   |     | 0       |       |
| eqTipoMascara         | int(11)          | NO   |     | 1       |       |
| eqAdvComunicacion     | int(11)          | NO   |     | 120     |       |
| eqFallaComunicacion   | int(11)          | NO   |     | 300     |       |
| eqStComs              | int(11)          | YES  |     | 0       |       |
| eqCiudadCercana       | int(11)          | YES  |     | NULL    |       |
| eqDistCiudadCercana   | float(11,0)      | YES  |     | NULL    |       |
| eqUsaGeocercaDinamica | int(1)           | NO   |     | 0       |       |
| eqUcStatus            | tinyint(4)       | NO   |     | 0       |       |
| eqOdometro            | float            | NO   |     | 0       |       |
| eqBoletin             | int(11)          | YES  |     | 0       |       |
| eqPaseSalida          | int(11)          | YES  |     | 0       |       |
| eqMedioTx             | varchar(20)      | YES  |     | 0       |       |
| eqDigInputs           | int(11)          | YES  |     | 0       |       |
| eqFechaActEqLocal     | datetime         | YES  |     | NULL    |       |
| eqLatitudCruda        | decimal(9,6)     | YES  |     | NULL    |       |
| eqLongitudCruda       | decimal(9,6)     | YES  |     | NULL    |       |
| eqVelocidadCruda      | int(11)          | YES  |     | NULL    |       |
| eqIconoWeb            | varchar(20)      | YES  |     | car     |       |
| eqUsaAnalogicas       | tinyint(4)       | NO   |     | 0       |       |
| eqInstalado           | tinyint(4)       | YES  |     | 0       |       |
| eqAcuerdo             | tinyint(4)       | YES  |     | NULL    |       |
| idEntidad             | int(11)          | YES  |     | NULL    |       |
| eqFallaECM            | tinyint(4)       | YES  |     | 0       |       |
+-----------------------+------------------+------+-----+---------+-------+

我认为这个表(由触发器引用)也可能是相关的:

mysql> describe shadow.tbl_chip;
+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| Id           | int(11)     | NO   | PRI | NULL    | auto_increment |
| ProviderId   | int(11)     | NO   | MUL | NULL    |                |
| OwnerId      | int(11)     | YES  | MUL | NULL    |                |
| ChipState    | varchar(15) | NO   | MUL | Nuevo   |                |
| AreaCode     | varchar(3)  | NO   |     | NULL    |                |
| Phone        | varchar(7)  | NO   |     | NULL    |                |
| SerialNumber | varchar(45) | NO   |     | NULL    |                |
| PIN          | varchar(4)  | YES  |     | NULL    |                |
| PUK          | varchar(45) | YES  |     | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+
9 rows in set (0.02 sec)

因此,基本上......每当通过命令行/ mysql-workbench发送查询时触发器触发,但不会在通过yii(与两个数据库模式托管在同一服务器中)发送时触发。我见过以下内容:

根据MySQL 5.0 documentation

  

MySQL触发器仅由SQL语句激活。它们不会被不会将SQL语句传输到MySQL服务器的API所做的更改激活;特别是,它们不会被使用NDB API进行的更新激活。

非常感谢任何帮助或指南。提前谢谢。

编辑:Yii使用PDO执行插入/更新语句,并且插入成功反映,更新仍然失败。

2 个答案:

答案 0 :(得分:1)

我正在使用AFTER UPDATE的触发器有一个子句,它以某种方式阻止在触发器内进行更改(实际上总是触发),

CREATE
DEFINER=`root`@`localhost`
TRIGGER `shadow`.`trg_device_after_update_reflect_changes`
AFTER UPDATE ON `shadow`.`tbl_device`
FOR EACH ROW
BEGIN
    DECLARE acuerdo TINYINT(4);
    DECLARE NumCel VARCHAR(10);
    DECLARE eqIdToUpdate INT;
    IF New.LastUpdated <> Old.LastUpdated THEN
        ...
    END IF;
END$$

每当从Yii更新时,New.LastUpdated <> Old.LastUpdated似乎都是假的,但每当从CLI或WorkBench更新时都是如此。因为在Yii应用程序上我没有收到tbl_device.LastUpdated的输入(我期待MySQL为我做这个工作,现在我觉得有点愚蠢,我可以使用beforeSave()方法更正时间戳字段我用来验证是否实际对记录进行了更改...)

答案 1 :(得分:0)

首先:尝试使用yii应用程序使用的相同mysql用户从console / workbench进行调试。

Yii仍然使用常规SQL语句,而不是您引用的文档中提到的api调用。

继续并输入config / main.php文件

components / db section:

'enableParamLogging' => true

和components / log部分:

    'log' => array(
        'class' => 'CLogRouter',
        'routes' => array(
            array(
                'class'=>'CFileLogRoute',
                'levels'=>'trace,log',
                'categories' => 'system.db.CDbCommand',
                'logFile' => 'db.log',
            ),
        ),
    ),

然后观察在protected / runtime / db.log中执行的sql命令:

$ tail -f db.log

另外,在更新主要触发器更新阴影触发器更新主触发器更新阴影触发器时,你确定你没有进入无限循环....?

相关问题