運用方針として、まちがってDELETEしたりしないために、削除フラグというカラムを
設けたりする場合があると思います。
(しないですか?)
※少なくとも、2人の知人に聞いたところ、1. 削除フラグを利用したことがある、
2. 削除フラグは常に利用している、という回答でした。
そこで、いろいろ考えてみたところ、削除フラグという考え方は、
RDBの以下の機能とバッティングするのではないかと思いました。
・外部キー制約のON DELETE CASCADEが利用できない
・参照先が削除された(delete_flag = 1)データであってもPRIMARY KEYを
参照できるので、外部キー制約違反にならない。
よって、参照整合性の維持を、DBを操作する側(PHPとか)で行わなくては
ならず、かなり面倒です。
解決案や、みなさんの考えをお聞きしたく思います。
※削除フラグカラムもプライマリーキーに含めて、マルチカラムプライマリーキーに
して、参照元でも、マルチカラムで参照するという方法があるかもしれませんが、
どうもしっくりいきません。
No.4ベストアンサー
- 回答日時:
#3です。
>> 削除フラグを利用するのは作業履歴が必要なもの。
>作業履歴!確かに、言われてみればそうですね。。
>可能であれば、削除データは別テーブルに移して、そこで履歴も保存したい
>ところですが、同じテーブルで削除フラグを利用したほうが、手っ取り早い
>というのはあるのかもしれません。
「削除フラグ」を「間違って削除」、「作業履歴」にも活用という点で、気になったのでコメントします。
「削除フラグ」で「誤って削除」を確認&復活させたり、「作業履歴を確認」というのは、かなり簡易的な方法で限界があると思います。
RDBMSのログを調べたり、トリガで履歴を残すといった方法の方が、一般的ではないでしょうか。
度々、ご回答ありがとうございます。
>「削除フラグ」で「誤って削除」を確認&復活させたり、「作業履歴を確認」というのは、かなり簡易的な方法で限界があると思います。
確かにそうですよね。「とりあえず感」が否めません。
>RDBMSのログを調べたり、トリガで履歴を残すといった方法の方が、一般的ではないでしょうか。
ログという方法もありますね。万が一の時に、DBAに泣きつくとか。。
トリガ!そうですね。トリガなら、かなり理想に近いことが出来そうです。
ただ、その場合、テーブルが500個あれば、トリガも500個必要になってきますでしょうか?
何か、いい方法ありますでしょうか?
No.5
- 回答日時:
最初に提示すべき情報が小出しにされ、自分で調べたり試行錯誤をしている様子もなく、あまり気持ちよくアドバイスできなくなってきましたが。
。。>ただ、その場合、テーブルが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
;
ご回答ありがとうございました。
SQL確認しました。これなら、削除フラグカラムを用意しなくても、
参照整合性を保ったまま、擬似削除ができますね。
この方法は初めて知りました。ありがとうございます。
ちなみに、この質問は幾分アンケート的にお伺いしたつもりです。
なのに、「人工キーを単独カラムで主キー」と後で付け加えたため、
あたかも、今まさに開発に取り掛かっていて困っているみたいな
雰囲気を出してしまい、申し訳ありませんでした。
念のため、付け加えておきます。
・トリガー
ON DELETE CASCADE は、トリガーを起動できないようなので諦めます。
http://dev.mysql.com/doc/refman/5.0/en/innodb-fo …
> Currently, triggers are not activated by cascaded foreign key actions.
・InnoDBの主キーの更新コスト
MyISAMと比べてということです。言葉足らずでした。
・MySQLのバージョン
特にバージョンは関係ないのです。どのDBMSということも関係ありません。
削除フラグを使うと、外部キーがややこしくなるけれども、皆さんは
どうされてますか?ということを聞きたかったのです。
・しっくりしないという意味
理由が明確な訳ではありませんが、私は、自然キーより人工キーを
主キーにする方がいいのではないかと思っています。
理由は、自然キーは変化する可能性があるということと、人工キーは、
いい加減な理由ですが、Ruby on Rails/symfony/cakePHPといった
FWで採用されているので、今の流行かな?また、第一カラムが
常にidなら、カラム名も考えなくていいし楽だ、という理由です。
また、私の考える人工キーとは、INT NOT NULL AUTO_INCREMENT のことであり、
全くなんの意味もない情報であるべきだと思っています。
ですので、ご提示いただいた例のように「値を負にする」ことによって、
擬似削除されたという「意味」を含有してしまうのは、私の考える人工キーに
反します。
主キーを更新するくらいなら、削除フラグの方を選ぶかもしれません。
削除フラグもいやだという理由は、せっかく完璧な人工キーがあるのに、
削除フラグカラムとセットになっているのでは、主キーが純粋に「人工的」に
ならないと思うためです。
ただ、これは私の、漠然とした考にすぎません。
ご意見、SQL例ありがとうございました。
No.3
- 回答日時:
テーブルの特性により、殆ど削除が発生しないものもあれば、頻繁に更新や削除を行うものもあります。
高性能を追求する上で、トラフィックの高い時間帯では、「削除フラグを立てる」(削除でなく、更新する)といった手法を採る場合もあります。
「削除フラグ」といった方法を採る場合、擬似削除したデータを、「いつまで残しておくか」、「いつ消すか」といったことを考慮する必要があります。これは、通常の操作時は、検索条件で「削除フラグが立っていないデータだけ扱う」ということでいいですが、バックアップ・リストア等を高速に行いたい場合などは、擬似削除したデータの分がオーバーヘッド要因になることがあるからです。
>外部キー制約のON DELETE CASCADEが利用できない
通常の操作では、ON DELETE CASCADEでなく、ON UPDATE CASCADEを利用することになります。メンテ日などで子テーブルのデータを実際に削除する場合、参照整合性に頼るより、参照整合性を働かないようにして、子テーブルのデータを一括して削除した方が早いこともあります。
>・参照先が削除された(delete_flag = 1)データであってもPRIMARY KEYを
>参照できるので、外部キー制約違反にならない。
「削除フラグ」といった方法を採るなら、親テーブルの操作にしても子テーブルの操作にしても、データを絞り込むキーに加え、「削除フラグが立っていない」という条件が必須になります。そうしないと、擬似削除したデータも操作することになります。
また、参照整合性使う場合、親の削除時には、子の削除も必須ですから、主キーと外部キーは、「削除フラグ」を含めた構成にする必要があります。
子だけ削除という場合を考えると、子テーブルには、さらに「子テーブルの削除」を示す「削除フラグ」が必要になり、子テーブルの操作時に検索条件で指定する必要があります。
ご回答ありがとうございます。
>高性能を追求する上で、トラフィックの高い時間帯では、「削除フラグを立てる」(削除でなく、更新する)といった手法を採る場合もあります。
そうなんですね。DELETEが高コストだとは知りませんでした。
>バックアップ・リストア等を高速に行いたい場合などは、擬似削除したデータの分がオーバーヘッド要因になることがあるからです。
必然的に、擬似削除したデータもバックアップを取ることになりますね。
>通常の操作では、ON DELETE CASCADEでなく、ON UPDATE CASCADEを利用することになります。
>また、参照整合性使う場合、親の削除時には、子の削除も必須ですから、主キーと外部キーは、「削除フラグ」を含めた構成にする必要があります。
その、「削除フラグ」を含めた構成にする、というのがどうもしっくりいきません。
InnoDBは、主キーの更新コストが高いらしいのですが、上記のようなマルチカラムで主キーにする場合はどうなるのでしょうか?
できれば、
id INT NOT NULL AUTO_INCREMENT
のような人工キーを単独で、主キーにしたいなと考えています。
No.1
- 回答日時:
個人的には削除というもの自体ほとんど使うことはありません。
削除フラグを利用するのは作業履歴が必要なもの。
例えば修正作業であってものそのアカクロ処理というのをするのが普通。
管理・設計者が必要があって削除するならともなく、使用者がなにかする
作業については削除(=なかったことにする)ということはあまり
考えられないとおもいます。
もちろんSQLの使い方は人それぞれなので、とっておく価値のないデータ
が頻繁に発生するようなシステムであれば、修正や削除を自由になさっても
問題はないと思いますが・・・
ご回答ありがとうございます。
> 削除フラグを利用するのは作業履歴が必要なもの。
作業履歴!確かに、言われてみればそうですね。。
可能であれば、削除データは別テーブルに移して、そこで履歴も保存したい
ところですが、同じテーブルで削除フラグを利用したほうが、手っ取り早い
というのはあるのかもしれません。
ただ、可能であれば、削除フラグというものはなんとかしたいですね。
(個人で何か作る時は削除フラグは使いません。)
ご意見、ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 教えて!goo なんで同じ質問を繰り返す人の質問に「指摘」すると削除されるのですか? 5 2023/06/08 20:37
- Visual Basic(VBA) Excelのマクロコードについて教えてください 1 2022/03/27 12:02
- Windows 10 Windows 10の[アプリと機能]に表示されない旧バージョンのアプリを削除したい 1 2022/04/05 20:25
- Chrome(クローム) Cookieを削除 他サイトでの自動ログインなどの設定も削除されますか パソコン クロームです 1 2022/09/10 21:47
- その他(IT・Webサービス) グーグルドメインズの解約方法 1 2022/08/14 12:52
- Excel(エクセル) 名前と日付が一致する箇所にフラグを立てる関数が知りたいです 4 2022/08/11 02:24
- Gmail GmailではメールをDelキーで削除可能でしょうか? 1 2022/08/17 10:43
- Outlook(アウトルック) Outlookでメールをデリートキーで削除した場合における、メールの移動先フォルダを変更したい。 2 2022/10/31 00:53
- フリーソフト USB内のフィアルの復活ソフトは? 4 2023/03/25 08:54
- X(旧Twitter) Twitterで一度完全削除したアカウントで同じ人が同じアカウントで最近復活 1 2023/03/30 18:02
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・「みんな教えて! 選手権!!」開催のお知らせ
- ・漫画をレンタルでお得に読める!
- ・「黒歴史」教えて下さい
- ・2024年においていきたいもの
- ・我が家のお雑煮スタイル、教えて下さい
- ・店員も客も斜め上を行くデパートの福袋
- ・食べられるかと思ったけど…ダメでした
- ・【大喜利】【投稿~12/28】こんなおせち料理は嫌だ
- ・前回の年越しの瞬間、何してた?
- ・【お題】マッチョ習字
- ・モテ期を経験した方いらっしゃいますか?
- ・一番最初にネットにつないだのはいつ?
- ・好きな人を振り向かせるためにしたこと
- ・【選手権お題その2】この漫画の2コマ目を考えてください
- ・2024年に成し遂げたこと
- ・3分あったら何をしますか?
- ・何歳が一番楽しかった?
- ・治せない「クセ」を教えてください
- ・【大喜利】【投稿~12/17】 ありそうだけど絶対に無いことわざ
- ・【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
- ・集合写真、どこに映る?
- ・自分の通っていた小学校のあるある
- ・フォントについて教えてください!
- ・これが怖いの自分だけ?というものありますか?
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・10代と話して驚いたこと
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
アクセス2010について
-
連番をふり直した後の文字の桁...
-
マージレプリケーション
-
SQLSERVERで関数作成?
-
大量のレコードを削除する方法
-
Excel テーブル内の空白行の削除
-
削除フラグってどうなんでしょう?
-
mysqlで間接クエリー実行させた...
-
Accessのテーブルをすべて削除
-
HiRDBのPURGEとDROPの違い
-
Access2000の削除クエリで消し...
-
テーブルが削除できない
-
条件付DELEATE文について
-
CSVファイルから一括して削除す...
-
シャンメリーが、硬くて開きま...
-
SELECT 文の NULL列は?
-
update文で改行を入れる
-
SQLにて指定日付より前、かつ最...
-
外部キーだけのテーブル(主キ...
-
SQL、2つのテーブルで条件一致...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Excel テーブル内の空白行の削除
-
アクセスのクエリでレコード削...
-
トリガって、自分自身のテーブ...
-
HiRDBのPURGEとDROPの違い
-
アクセス2010について
-
ACCESSのマクロでテーブルのデ...
-
CSVファイルから一括して削除す...
-
Access2000の削除クエリで消し...
-
テーブルデータの削除による対応策
-
mysqlで間接クエリー実行させた...
-
Accessのテーブルをすべて削除
-
アクセス通貨型or数値型について
-
削除フラグってどうなんでしょう?
-
リレーションについて
-
ワークテーブルなのに自動で削...
-
列のDEFAULT設定を削除するコマ...
-
MySQLのストアドでファイルを削除
-
MySQLを勉強中ですが、作業の内...
-
レコードの削除で delete from ...
-
物理削除と論理削除、どっちが...
おすすめ情報