ユニーク制約などの違反時に指定の値で上書きする
テーブルの中のカラムにプライマリーキー制約やユニーク制約が設定されている場合に、データを追加すると制約違反となる場合があります。このような場合通常はエラーとなりますが、エラーを発生させる代わりに既存のデータを指定の値で上書きすることができます。
次の書式を使います。
INSERT INTO tbl_name (col_name1, col_name2, ...) VALUES (value1, value2, ...) ON DUPLICATE KEY UPDATE col_name_x=value_x, col_name_y=value_y, ...;
ユニーク制約などで違反するデータを追加しようとした時に、データを新規に追加するかわりに既存のデータの指定のカラムの値を更新するということです。この時、更新するカラムは複数指定できますが、エラーの元となるユニーク制約などが設定されたカラムの値は更新できません。またエラーが出ずに新規に追加が成功した場合に格納する値と、エラーが発生し既存のデータを更新する場合の値を別々に指定することができます。
では実際に試してみます。次のようなテーブルを作成しました。
mysql> create table usertbl(user varchar(20) unique, visit int, browse int);
「user」カラムにはユニーク制約が設定してありますので、重複した値を持つことはできません。
ではデータを追加します。次のように入力して下さい。
mysql> insert into usertbl values('yamada', 1, 5) -> on duplicate key update visit=visit+1, browse=browse+5;
新規にデータが追加されました。
この場合、エラーが発生しない場合には新規にデータを追加します。またユニーク制約のエラーが発生した場合には「user」カラムの値が'yamada'のデータを更新します。更新はまず「visit」カラムの値を取り出し1を加えて再度格納し、同じように「browse」カラムの値を取り出し5を加えた値を格納するようにしています。
今回更新する値として「visit+1」や「browse+5」という記述をしていますが、値の部分でカラム名を記述すると、対象データの指定したカラムの値を参照することができます。
では「user」カラムの値が既に存在するようなデータを追加します。次のように入力して下さい。
mysql> insert into usertbl values('yamada', 1, 7) -> on duplicate key update visit=visit+1, browse=browse+7;
今回はユニーク制約に違反するデータを追加しようとしたため、新規にデータを追加するのではなく「user」カラムの値が'yamada'のデータに対して「visti」カラムと「browse」カラムの値を新しい値で更新しています。
VALUES関数
更新する値を指定する部分でVALUES(col_name)を使用すると、引数のカラムに対して新規でデータが追加する場合に格納するはずの値を参照できます。
例えば次のようなSQL文を例に考えてみます。
mysql> insert into usertbl values('yamada', 1, 7) -> on duplicate key update visit=visit+1, browse=browse+7;
これは次のように記述することもできます。
mysql> insert into usertbl values('yamada', 1, 7) -> on duplicate key update visit=visit+1, browse=browse+values(browse);
エラーが発生しない場合には「browse」カラムに7を格納しようとしていますので、values(browse)は7を返すことになります。
( Written by Tatsuo Ikura )