データを保存するテーブルがいくつかあり、event
テーブルに保存したい仕事をした人のタイプ(労働者、市民)に応じて、これらの人が動物を救出します(animal
テーブルがあります)。
最後に、男(労働者、市民)が動物を救ったというイベントを格納するテーブルが欲しいのですが、外部キーを追加する必要があるのでしょうか、それとも、仕事をした市民または労働者のid
値を知る方法はありますか?
さて、この設計では、どの人が仕事をしたかを関連付ける方法がわかりません、私は一種の人(別名市民)しかいなかったので、この最後のテーブルのperson
列にcivil_id
値のみを保存します...しかし、それが民事か労働者かを知る方法、私は他の「中間」テーブルが必要ですか?
次の図の設計をMySQLに反映するにはどうすればよいですか?
私はそれを次のようにモデル化しました:
DROP TABLE IF EXISTS `tbl_animal`;
CREATE TABLE `tbl_animal` (
id_animal INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(25) NOT NULL DEFAULT "no name",
specie VARCHAR(10) NOT NULL DEFAULT "Other",
sex CHAR(1) NOT NULL DEFAULT "M",
size VARCHAR(10) NOT NULL DEFAULT "Mini",
edad VARCHAR(10) NOT NULL DEFAULT "Lact",
pelo VARCHAR(5 ) NOT NULL DEFAULT "short",
color VARCHAR(25) NOT NULL DEFAULT "not defined",
ra VARCHAR(25) NOT NULL DEFAULT "not defined",
CONSTRAINT `uc_Info_Animal` UNIQUE (`id_animal`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tbl_animal` VALUES (1,'no name', 'dog', 'M','Mini','Lact','Long','black','Bobtail');
INSERT INTO `tbl_animal` VALUES (2,'peluchin', 'cat', 'M','Mini','Lact','Long','white','not defined');
INSERT INTO `tbl_animal` VALUES (3,'asechin', 'cat', 'M','Mini','Lact','Corto','orange','not defined');
DROP TABLE IF EXISTS `tbl_person`;
CREATE TABLE `tbl_person` (
type_person VARCHAR(50) NOT NULL primary key
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tbl_person` (type_person) VALUES ('Worker');
INSERT INTO `tbl_person` (type_person) VALUES ('Civil');
DROP TABLE IF EXISTS `tbl_worker`;
CREATE TABLE `tbl_worker`(
id_worker INTEGER NOT NULL PRIMARY KEY,
type_person VARCHAR(50) NOT NULL ,
name_worker VARCHAR(50) NOT NULL ,
address_worker VARCHAR(40) NOT NULL DEFAULT "not defined",
delegation VARCHAR(40) NOT NULL DEFAULT "not defined",
FOREIGN KEY (type_person) REFERENCES `tbl_person` (type_person),
CONSTRAINT `uc_Info_worker` UNIQUE (`id_worker`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tbl_worker` VALUES (1,'Worker','N_CEDENTE1', 'DIR Worker 1', 'DEL');
INSERT INTO `tbl_worker` VALUES (2,'Worker','N_worker1', 'DIR Worker 2', 'DEL');
INSERT INTO `tbl_worker` VALUES (3,'Worker','N_worker2', 'address worker','delegation worker');
DROP TABLE IF EXISTS `tbl_civil`;
CREATE TABLE `tbl_civil`(
id_civil INTEGER NOT NULL PRIMARY KEY,
type_person VARCHAR(50) NOT NULL ,
name_civil VARCHAR(50) ,
procedence_civil VARCHAR(40) NOT NULL DEFAULT "Socorrism",
FOREIGN KEY (type_person) REFERENCES `tbl_person` (type_person),
CONSTRAINT `uc_Info_civil` UNIQUE (`id_civil`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tbl_civil` VALUES (1,'Civil','N_civil1' , 'Socorrism');
CREATE TABLE `tbl_event` (
id_event INTEGER NOT NULL,
id_animal INTEGER NOT NULL,
type_person VARCHAR(50) NOT NULL ,
date_reception DATE DEFAULT '2000-01-01 01:01:01',
FOREIGN KEY (id_animal) REFERENCES `tbl_animal` (id_animal),
FOREIGN KEY (type_person ) REFERENCES `tbl_person` (type_person ),
CONSTRAINT `uc_Info_ficha_primer_ingreso` UNIQUE (`id_animal`,`id_event`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `tbl_event` VALUES (1,1, 'Worker','2013-01-01 01:01:01' );
INSERT INTO `tbl_event` VALUES (2,2, 'Civil','2013-01-01 01:01:01' );
しかし、ヌルを取り除く方法はありますか?
私が持っているクエリは:
SELECT a.*,b.*,z.*
FROM tbl_event a
left JOIN tbl_worker b
ON a.type_person = b.type_person
left JOIN tbl_animal z
ON z.id_animal = a.id_animal ;
SELECT a.*,b.*,z.*
FROM tbl_event a
left JOIN tbl_civil b
ON a.type_person = b.type_person
left JOIN tbl_animal z
ON z.id_animal = a.id_animal ;
これが更新された sqlfiddleです。
ダイアグラムを作成したので、私はよりよく答えます;)
残念ながら現在のリレーショナルデータベースは継承を直接サポートしていないため、「プレーン」テーブルに変換する必要があります。これを行うには、一般に3つの方法があります。
これが実際に何を意味するか、そしていくつかの長所と短所については、私の 元の投稿 で提供されているリンクを参照してください。ただし、具体的な理由がない限り、簡単に言えば(3)がデフォルトになります他の2つのうちの1つ。次のように、データベースで(3)を表すことができます。
CREATE TABLE person (
person_id int PRIMARY KEY
-- Other fields...
);
CREATE TABLE civil (
civil_id int PRIMARY KEY REFERENCES person (person_id)
-- Other fields...
);
CREATE TABLE worker (
worker_id int PRIMARY KEY REFERENCES person (person_id)
-- Other fields...
);
CREATE TABLE event (
event_id int PRIMARY KEY,
person_id int REFERENCES person (person_id)
-- Other fields...
);
残念ながら、この構造では、person
でもcivil
でもないworker
を使用でき(つまり、抽象クラスをインスタンス化できます)、person
を作成できますbothcivil
およびworker
。 方法があります 前者をデータベースレベルで適用し、DBMSで遅延制約をサポートする3 後者でもデータベース内で実施できますが、これはアプリケーションレベルの整合性を使用することが実際に望ましい数少ないケースの1つです。
1 この場合、person
、civil
、worker
。
2 この場合、civil
およびworker
(person
は "abstract")です。
3 どのMySQLはそうしません。
個別のCivil_IDとWorker_IDは必要ありません。 Person-IDを、Person、Civil、Workerの3つのテーブルすべてのキーとして引き続き使用します。 「Civil」と「Worker」の2つの値を持つ列PersonTypeをPersonに追加します。
これは、基本エンティティPersonのサブエンティティCivilおよびWorkerとして、抽象基本クラスPersonClassの2つのサブクラスCivilClassおよびWorkerClassを表します。 DBのデータモデルとアプリケーションのオブジェクトモデルがうまく対応します。
あなたのケースは、クラス/サブクラスモデリングのインスタンスです。または、ERで図化したように、汎化/特殊化。
このケースをカバーするmysqlテーブルの設計に役立つ3つのテクニックがあります。これらは、単一テーブル継承、クラステーブル継承、および共有主キーと呼ばれます。あなたはSOの対応するタグから情報タブでそれらを読むことができます。
https://stackoverflow.com/tags/single-table-inheritance/info
https://stackoverflow.com/tags/class-table-inheritance/info
https://stackoverflow.com/tags/shared-primary-key/info
単一テーブルの継承は、NULLの存在が問題を引き起こさない単純な場合に役立ちます。クラステーブルの継承は、より複雑な場合に適しています。共有主キーは、1対1の関係を強制し、結合を高速化するための良い方法です。
個人タイプテーブルを作成し、タイプの適用が必要なすべてのテーブルにフィールドを追加できます。次に、外部キーを作成します。これはあなたのものから派生した例です...
CREATE TABLE person_type (
person_type_id int PRIMARY KEY
-- data: 1=civil, 2=worker
-- Other fields (such as a label)...
);
CREATE TABLE person (
person_id int PRIMARY KEY
person_type_id int FOREIGN KEY REFERENCES person_type (person_type_id)
-- Other fields...
);
CREATE TABLE civil (
civil_id int PRIMARY KEY REFERENCES person (person_id)
person_type_id int FOREIGN KEY REFERENCES person (person_type_id)
-- Other fields...
);
CREATE TABLE worker (
worker_id int PRIMARY KEY REFERENCES person (person_id)
person_type_id int FOREIGN KEY REFERENCES person (person_type_id)
-- Other fields...
);
CREATE TABLE event (
event_id int PRIMARY KEY,
person_id int REFERENCES person (person_id)
-- Type is optional here, but you could enforce event for a particular type
person_type_id int FOREIGN KEY REFERENCES person (person_type_id)
-- Other fields...
);