php - Yii 应用程序未激活的触发器

标签 php mysql pdo yii

大家好StackOverflow,我是本站的Fan,帮我走出了无数的坑。但是这次我似乎没有在这里或其他任何地方找到答案,我的问题是:

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

我的开发是为了支持一个已经存在的模式(我将其称为 ma​​in),它有几个设计问题。我们的目标是用一个新的、正确设计的模式替换旧模式(我将其称为 shadow)。但与此同时,我们正在尝试将新架构作为主要架构的影子架构来实现,并通过触发器保持更改的一致性。

所有重要更改均针对影子模式进行,影子模式使用触发器将其反射(reflect)到主模式。两种模式都托管在同一台服务器上,并且只要通过命令行客户端或使用 MySQL Workbench 进行更改,触发器就可以很好地反射(reflect)数据从影子到主要的变化,但是每当我使用我的 Yii 应用程序进行更改以影子数据时......仅对影子模式进行更改,不会触发反射(reflect)到主模式。

这是 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中的trigger是为了反射(reflect)main的变化的trigger,这里是ma​​in.equipos的描述(目前没有使用trigger):

+-----------------------+------------------+------+-----+---------+-------+
| 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 triggers are activated by SQL statements only. They are not activated by changes in tables made by APIs that do not transmit SQL statements to the MySQL Server; in particular, they are not activated by updates made using the NDB API.

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

编辑: Yii 使用 PDO 做插入/更新语句,插入成功反射(reflect),更新仍然失败。

最佳答案

我正在使用的触发器 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$$

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

关于php - Yii 应用程序未激活的触发器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13127700/

相关文章:

mysql - 为每个不同的出现计算行号

php - SQLSTATE[01002] Adaptive Server 连接失败(严重性 9)

PHP MySQL PDO lastInsertID 导致 fatal error

php - 使用数组和foreach检索多个数据并插入多个数据

php - SQL查询两个表

php - 长数字字符串模式的逻辑,在php中添加空格

mysql - rsyslog ommysql 按优先级过滤

php - PDO 在单个查询中插入数据两次

javascript - 用于检查自定义下拉列表中必填字段的 JQuery 函数中的错误

php - Symfony2 表单,与实体不匹配