大家好 StackOverflow 的各位,我是本站的粉丝,帮我走出了无数的坑。但是这次我似乎在这里或其他任何地方都找不到答案,我的问题是:
我正在开发一个 Yii 框架应用程序来处理数据库中的数据,保持一致性和一切。基本上,我正在创建一个用于操作数据库信息的界面。我正在使用 MySQL 5.0(计划更新到 5.5)和 InnoDB。
我的开发将支持一个已经存在的模式(我称之为main),它有几个设计问题。我们的目标是用设计正确的新模式(我称之为shadow)替换旧模式。但与此同时,我们正在尝试将新模式实现为主要模式的影子模式,并通过触发器保持更改的一致性。
所有重要的更改都对影子模式进行,它使用触发器将其反映到主模式。两种模式都托管在同一台服务器中,每当通过命令行客户端或使用 MySQL Workbench 进行更改时,触发器都能很好地反映从影子到主的数据更改,但每当我使用 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 触发器仅由 SQL 语句激活。它们不会被不将 SQL 语句传输到 MySQL 服务器的 API 对表所做的更改激活;特别是,它们不会被使用 NDB API 所做的更新激活。
非常感谢任何帮助或指导。提前致谢。
编辑: Yii 使用 PDO 执行插入/更新语句,插入反映成功,更新仍然失败。