2017-02-21 7 views
4

私は、MySQL 5.7で働いている:INSERT ON DUPLICATE KEY UPDATEのトリガ前のMySQL - マニュアルが間違っているようですか?

は、BEFORE INSERTトリガーは、行ごとにアクティブに

、続い:

D:\>mysql --version 
mysql Ver 14.14 Distrib 5.7.17, for Win64 (x86_64) 

manualによると、BEFORE INSERTトリガーの動作が可能になっています行の重複キーがあったかどうかによって、 AFTER INSERTトリガー、またはBEFORE UPDATEとAFTER UPDATEの両方のトリガーがトリガーされます( トリガー)。 INSERTおよびUPDATEトリガーは、キーの競合があるのか​​どうかに依存しているしばらく私はこれを取る

は、BEFORE INSERTは関係なく、重複キーマッチがありますかどうかに実行されることを意味します。 This SOも同じです。しかし、私はこの動作を見ていません。ここに私がしたことがあります:

create table testtable (
    id integer primary key auto_increment, 
    nickname varchar(40), -- this is the natural key to be unique indexed 
    name varchar(40), 
    uuid varchar(36));  -- this is what I want to assign in the trigger 

alter table testtable add unique index testtable_ux (nickname); 
create trigger testtable_uid before insert on testtable for each row set 
    new.uuid=uuid(); 

-- get some data 
insert into testtable (nickname, name) values ('bob', 'Robert'), 
    ('fred', 'Frederick'), ('cha', 'Chauncey'); 
select * from testtable; 

1 bob Robert  06fb18be-f87e-11e6-8e6f-0060737a7c01 
2 fred Frederick 06fb1a5d-f87e-11e6-8e6f-0060737a7c01 
3 cha Chauncey 06fb1aec-f87e-11e6-8e6f-0060737a7c01 

ニース - それぞれの男はユニークなUUIDを持っています。今すぐマニュアルに従って、このBEFORE INSERTトリガーは、重複キーがあるかどうかに関係なく実行されるはずです。重複キー更新を取得しても、UUIDを更新する必要があります。見てみましょう:

insert into testtable (nickname, name) values ('fred', 'Alfred') 
    on duplicate key update name='Alfred'; 
3 88 16:39:32 ... 2 row(s) affected 0.032 sec 

select * from testtable; 
1 bob Robert  06fb18be-f87e-11e6-8e6f-0060737a7c01 
2 fred Alfred  06fb1a5d-f87e-11e6-8e6f-0060737a7c01 
3 cha Chauncey 06fb1aec-f87e-11e6-8e6f-0060737a7c01 

名前が更新されました。

2 fred Frederick 06fb1a5d-f87e-11e6-8e6f-0060737a7c01 
2 fred Alfred  06fb1a5d-f87e-11e6-8e6f-0060737a7c01 

upsertは期待通りに実行されましたが、UUIDは再生成されませんでした。私は定数の文字列でこれを試して、同じ結果を得る。

これはまさに私が起こりたいことです。 upsertのどの枝をとっているかにかかわらず起きるBEFORE INSERTは、かなり役に立たないようです。少なくとも、この動作はもっと便利です。しかし、それはマニュアルが言っているものに反するようです。どんな洞察?

+0

私の推測を:新しい 'uuid'が生成されますがありません割り当てられた。なぜそれはすべきだと思いますか?あなたはduplikateキーで何が起こるべきかを正確に伝えます: 'name = 'Alfred''。なぜUUIDが変わると思うのですか? –

+0

@PaulSpiegel考えてくれてありがとう、しかし私はそこに "セット"を持っています。これは、最初の挿入時に機能します。つまり、カラムが最初に挿入される方法です。 – fool4jesus

答えて

3

BEFORE INSERTトリガーが重複して発生します。ログテーブルを使ってテストできます。私はあなたのコードに、このようなテーブルを追加し、そのテーブルを移入するためにトリガーを変更した:

drop table if exists testtable; 
create table testtable (
    id integer primary key auto_increment, 
    nickname varchar(40), -- this is the natural key to be unique indexed 
    name varchar(40), 
    uuid varchar(36));  -- this is what I want to assign in the trigger 

alter table testtable add unique index testtable_ux (nickname); 

drop table if exists testlog; 
create table testlog (
    log_id int primary key auto_increment, 
    nickname varchar(40), 
    name varchar(40), 
    uuid varchar(36) 
); 

drop trigger if exists testtable_uid; 
delimiter // 
create trigger testtable_uid before insert on testtable for each row 
begin 
    set new.uuid=uuid(); 
    insert into testlog (nickname, name, uuid) values (new.nickname, new.name, new.uuid); 
end // 
delimiter ; 

insert into testtable (nickname, name) values ('bob', 'Robert'), 
    ('fred', 'Frederick'), ('cha', 'Chauncey'); 
select * from testtable; 

insert into testtable (nickname, name) values ('fred', 'Alfred') 
    on duplicate key update name='Alfred'; 

select * from testtable; 
select * from testlog; 

あなたはtestlogテーブルが4行を持っていることがわかります。最後のものには 'fred'、 'Alfred'と新しいUUIDが含まれています。つまり、引き金が発砲されたことを意味します。つまり、新しいUUIDが生成されたことを意味します。しかし、そのUUIDはtesttable.uuidに割り当てられませんでした。あなたのコードにそうするよう指示するものは何もありません。

あなたはON DUPLICATE部に割り当てられる(トリガーで生成された)新しいUUIDをしたい場合、あなたはvalues(uuid)とそれをアクセスもできます。

insert into testtable (nickname, name) values ('fred', 'Alfred') 
    on duplicate key update 
    name='Alfred', 
    `uuid`=values(`uuid`); 
+0

私は参照してください。あなたが言っていることは、トリガが実行されていることと "新しい"レコードが移入されていることですが、UPDATE句でvalues()関数を使用しない限り、実際には更新の場合は何も行いません。それは理にかなっている。ありがとうございました! – fool4jesus

関連する問題