0

行をテーブルに挿入する前に実行したいトリガーがあります。

CREATE TABLE IF NOT EXISTS `test`.`t1`(
  `idt1` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `myType` ENUM('A','B','C') NOT NULL DEFAULT 'A',
  PRIMARY KEY (`idt1`) )
ENGINE = InnoDB;

delimiter $$
CREATE TRIGGER mtCheck BEFORE INSERT ON t1
FOR EACH ROW
BEGIN
    set @action = NEW.myType;
IF (NEW.myType NOT LIKE 'B') THEN
            SET New.myType = 'C';
    END IF;
    set @action2 = NEW.myType;
END $$
delimiter ;

以下のコードを実行すると、'A' は EMUN の有効な値であるため、@action は 'A' で @action2 は 'C' です。

set @action = 'no action';
set @action2 = 'no action';
select @action, @action2;
start transaction;
insert into t1(idt1, myType) values (1, 'A');
select @action, @action2;
select * from t1;
rollback;
select * from t1;
select @action, @action2;

次の例のいずれかの挿入ステートメントを変更すると、次のエラーが表示されます。

insert into t1(idt1, myType) values (1, 'F');

-> エラー 1265 (01000): 行 1 の列 'myType' のデータが切り捨てられました

insert into t1(idt1, myType) values (1, null);

-> エラー 1048 (23000): 列 'myType' を null にすることはできません

トリガーが新しい値を NEW.myType フィールドに強制し、insert ステートメントが正しい値で続行されるべきではありませんか? この場合、両方の例で、テーブル t1 の myType フィールドに値「C」を入力する必要があります。

それは私のsql_modeと関係がありますか?

SELECT @@GLOBAL.sql_mode;

-> STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

SELECT @@SESSION.sql_mode;

-> STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

に変更する必要がありSTRICT_ALL_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTIONますか?

4

1 に答える 1

0

私は自分の間違いに気づいたと信じています。

トランザクション内で元のテーブル行を挿入/更新するために作成される一時テーブルには、元のテーブルと同じ制限があります。

この分析が正確である場合、テーブル行を挿入/更新する前に、データベース管理システムが挿入/更新されている値を検証し、有効なデータを提供していないため、上記のエラーを返すことを意味します。

データベースへの接続を確立する前に、検証をアプリケーションに任せる必要があります。

于 2012-08-01T18:04:02.280 に答える