最初に提示すべき情報が小出しにされ、自分で調べたり試行錯誤をしている様子もなく、あまり気持ちよくアドバイスできなくなってきましたが。。。
>ただ、その場合、テーブルが500個あれば、トリガも500個必要になってきますでしょうか?
そんなのは、ケースバイケースです。前に回答したように、テーブルの特性によります。
>その、「削除フラグ」を含めた構成にする、というのがどうもしっくりいきません。
「しっくりしない」といった曖昧な表現では、アドバイスのしようがありません。
>InnoDBは、主キーの更新コストが高いらしいのです
InnoDB、あるいはMySQLに限った話ではないですが?
>上記のようなマルチカラムで主キーにする場合はどうなるのでしょうか?
>できれば、
> id INT NOT NULL AUTO_INCREMENT
>のような人工キーを単独で、主キーにしたいなと考えています。
こういった情報は、最初に提示してください。また、MySQLのバージョンも未提示ですよね?
「削除の印」は、必ずしもフラグ用の列を設けなければならない訳ではありません。例えば、主キーをcharなどで定義し、アプリ側では「主キー+削除フラグ」といった構造体で参照するといった方法もあります。ただ、そういう方式にすると、MySQLのauto_incrementは使えなくなります。
こういった方法でなくても、行を一意に識別でき、なおかつ有効なデータかどうかが分かればいいので、例えば提示のケースでは、擬似削除の印として、「id列の値を負にする」といった方法もあります。ただ、インデクスの先頭構成列の更新は、高コストになるので、できれば避けたいところです。
最後にSQL例を示しますので、自分でも調べたり、試行錯誤してみてください。
=====例題=====
drop table if exists t11;
drop table if exists t21;
create table t11
(t11key int not null auto_increment,
t11data varchar(30),
t11log timestamp,
primary key(t11key) # 削除データは負で表す
-- primary key(t11key,t11flag) # auto_incrementが先頭なら、InnoDBでも動く
-- MySQLで保証した使い方かは未確認
-- primary key(t11flag,t11key) # auto_incrementが2番目なら、1075で想定通りエラー
)
engine=innodb
;
create table t21
(t21key bigint primary key auto_increment, # 削除は負で表す
t11key int not null,
t21data varchar(30),
t21log timestamp,
constraint t11t21
foreign key(t11key)
references t11(t11key)
on delete cascade
on update cascade
)
engine=innodb
;
insert into t11(t11data) values
('aaa'),
('ccc'),
('eee');
insert into t21(t11key,t21data)
select
t11key,
'aaa1'
from t11
where t11data='aaa' and t11key>0
;
insert into t21(t11key,t21data)
select
t11key,
'ccc1'
from t11
where t11data='ccc' and t11key>0
;
insert into t21(t11key,t21data)
select
t11key,
'ccc2'
from t11
where t11data='ccc' and t11key>0
;
insert into t21(t11key,t21data)
select
t11key,
'ccc3'
from t11
where t11data='ccc' and t11key>0
;
-- 結果確認(全データ)
select * from t11 order by t11key;
select * from t21 order by t11key,t21key;
-- 結果確認(有効データのみ)
select * from t11 where t11key>0 order by t11key;
select * from t21 where t21key>0 and t11key>0 order by t11key,t21key;
-- 親の擬似削除(参照整合性の動作で、子も擬似削除)
update t11
set t11key=-t11key
where t11key=1
;
-- 子だけの擬似削除
update t21
set t21key=-t21key
where t21key=3 and t11key>0
;
お礼
度々、ご回答ありがとうございます。 >「削除フラグ」で「誤って削除」を確認&復活させたり、「作業履歴を確認」というのは、かなり簡易的な方法で限界があると思います。 確かにそうですよね。「とりあえず感」が否めません。 >RDBMSのログを調べたり、トリガで履歴を残すといった方法の方が、一般的ではないでしょうか。 ログという方法もありますね。万が一の時に、DBAに泣きつくとか。。 トリガ!そうですね。トリガなら、かなり理想に近いことが出来そうです。 ただ、その場合、テーブルが500個あれば、トリガも500個必要になってきますでしょうか? 何か、いい方法ありますでしょうか?