私は、ワークベンチで遊んだり、プロジェクト用にこのデータベースを設定する方法を理解したりすることから得たもの以外に、データベースの経験はありません。私はインターネットを検索していて、自分がやりたいことをどのように行うのかについて、ますます混乱しています。以下は私が達成しようとしていることです。
患者情報を保持するMySQLデータベースが必要です。患者情報は、名前、ID(一意)など、すべてのテストと各テストのサンプルになります。
これまでのところ、リレーショナルデータベースが必要であることを理解しています。また、外部キーを使用して各テーブルの患者IDと各テーブルのテストIDをリンクできることも理解しています。また、行の削除と更新を手動で管理する必要がないように、データの整合性が必要であるという結論にも達しました。これも孤立した行を許可しません。これは複合キーで実行できると思いますが、ここで設定方法が混乱し始めます。
私はそれが次のように機能することを期待します(各行が挿入ステートメントです):
患者テーブル:
|-------------------|
|Patient ID |Name |
|-------------------|
|12345 |ANG |
|54321 |JUE |
|-------------------|
テストテーブル:
|----------------------|
|Test ID |Patient ID |
|----------------------|
|1 |12345 |
|2 |12345 |
|3 |12345 |
|1 |54321 |
|2 |54321 |
|4 |12345 |
|----------------------|
サンプルテーブル:
|----------------------------------|
|Sample ID |Test ID |Patient ID |
|----------------------------------|
|1 |1 |12345 |
|2 |1 |12345 |
|3 |1 |12345 |
|1 |2 |12345 |
|1 |1 |54321 |
|1 |2 |54321 |
|2 |2 |54321 |
|2 |2 |12345 |
|----------------------------------|
これは簡単にできますか?これは1つまたは2つのトリガーで実行できることも知っていますが、削除などを処理しないことを理解しました。これを実行するのが簡単な別の方法はありますか?また、このデータベースに書き込まれたり読み取られたりするデータは、LabVIEWプログラムによって処理されます。
Joel、Greenstone、Stolegに感謝します。さらに調査した後、y'allのコメントと回答は、自分が必要なものを理解するのに役立ちました。トリガーとデータの整合性に関しては、考えすぎていたことがわかりました。
必要なものの要約:
患者テーブル:なし
テストテーブル:一意の外部キー(Patient ID
)ごとに、Test ID
は1から始まります
サンプルテーブル:一意の複合外部キー(Test ID
AND Patient ID
)ごとに、Sample ID
は1から始まります。
- 各患者は複数の検査を受けることができます
- 各テストには複数のサンプルを含めることができます
- 患者を削除すると、すべてのテストとサンプルが削除されます
- テストを削除すると、すべてのサンプルが削除されます
- 1つのテストのすべてのサンプルを削除する場合OR 1人の患者のすべてのテストの場合、テストOR患者は削除しないでください。
回答:
これは、トリガーを使用して実装し、データの整合性を維持するのが非常に簡単です。 Joelが言うように、データは非常に直接的な構造であり、多数のsamples
から1つtest
、多数のtests
から1つpatient
があり、一意のみです。 patients
テーブルのpatient
。これにより、カスケードを使用して孤立を防止し、データの整合性を維持できます。カスケードを設定すると、必要なすべての項目が満たされます。ジョエルの例:
...
CONSTRAINT 'FK_TEST__PATIENT' FOREIGN KEY ('patient_id')
REFERENCES 'PATIENT' ('patient_id') ON DELETE CASCADE
...
CONSTRAINT 'FK_SAMPLE__TEST' FOREIGN KEY ('test_id')
REFERENCES 'TEST' ('test_id') ON DELETE CASCADE
...
次の部分は、一意のキーまたは複合キーごとに自動インクリメント(これは組み込みのauto-incではありません)をリセットすることでした。これは、BEFORE INSERT
トリガーを使用して実行できます。 (クレジットは Devart に移動します)
これは私のtest
テーブルの変更されたトリガーです:
delimiter $$
CREATE TRIGGER `insert_test_auto_inc`
BEFORE INSERT
ON `tests`
FOR EACH ROW
BEGIN
SELECT COALESCE(MAX(`Test ID`) + 1, 1) INTO @`Test ID` FROM tests WHERE `Patient ID` = NEW.`Patient ID`;
SET NEW.`Test ID` = @`Test ID`;
END
$$
MAX
関数から始まるトリガーコードの動作。 Nullの最大値はNullであり、Null + 1はNullです。 COALESCE
関数は最初のNull以外の値を返すため、Test ID
が定義されていない場合は、コンマの後の1になります。 Test ID
が値、たとえば1の場合、1 + 1 = 2に1を加えた値を返します。INTO
部分は、その値をユーザー変数@Test ID
に入れます。最大値は、Patient ID
に一致する行でのみ見つかります。この自動インクリメントされた(組み込みではなくコードによって)値は、Test ID
のNEW
値に書き込まれます。
これは私のsample
テーブルの変更されたトリガーです:
delimiter $$
CREATE TRIGGER `insert_sample_auto_inc`
BEFORE INSERT
ON `samples`
FOR EACH ROW
BEGIN
SELECT COALESCE(MAX(`Sample ID`) + 1, 1) INTO @`Sample ID` FROM samples WHERE `Patient ID` = NEW.`Patient ID` AND `Test ID` = NEW.`Test ID`;
SET NEW.`Sample ID` = @`Sample ID`;
END
$$
WHERE
ステートメントを使用してPatient ID
とTest ID
の両方に一致することを除いて、サンプルトリガーでも同じことが起こります。
以下は、この質問が望むように機能するこのサンプルデータベースを作成するために必要なすべてのコマンドです。このコードはMySQL Workbenchを使用して生成されました。
delimiter $$
CREATE DATABASE `testdb` /*!40100 DEFAULT CHARACTER SET utf8 */$$
delimiter $$
CREATE TABLE `patients` (
`Patient ID` int(10) unsigned NOT NULL,
`First Name` varchar(45) DEFAULT NULL,
`Last Name` varchar(45) DEFAULT NULL,
`DOB` varchar(45) DEFAULT NULL,
PRIMARY KEY (`Patient ID`),
UNIQUE KEY `PatientID_UNIQUE` (`Patient ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
delimiter $$
CREATE TABLE `tests` (
`Test ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Patient ID` int(10) unsigned NOT NULL,
PRIMARY KEY (`Test ID`,`Patient ID`),
KEY `fk_tests_patient_id_idx` (`Patient ID`),
CONSTRAINT `fk_tests_patient_id` FOREIGN KEY (`Patient ID`) REFERENCES `patients` (`Patient ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8$$
CREATE
DEFINER=`root`@`localhost`
TRIGGER `testdb`.`insert_test_auto_inc`
BEFORE INSERT ON `testdb`.`tests`
FOR EACH ROW
-- Edit trigger body code below this line. Do not edit lines above this one
BEGIN
SELECT COALESCE(MAX(`Test ID`) + 1, 1) INTO @`Test ID` FROM tests WHERE `Patient ID` = NEW.`Patient ID`;
SET NEW.`Test ID` = @`Test ID`;
END
$$
delimiter $$
CREATE TABLE `samples` (
`Sample ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Test ID` int(10) unsigned NOT NULL,
`Patient ID` int(10) unsigned NOT NULL,
`Count Value` int(11) DEFAULT NULL,
PRIMARY KEY (`Sample ID`,`Test ID`,`Patient ID`),
KEY `fk_samples_test_id_idx` (`Test ID`),
KEY `fk_samples_patient_id_idx` (`Patient ID`),
CONSTRAINT `fk_samples_patient_id` FOREIGN KEY (`Patient ID`) REFERENCES `patients` (`Patient ID`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_samples_test_id` FOREIGN KEY (`Test ID`) REFERENCES `tests` (`Test ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8$$
CREATE
DEFINER=`root`@`localhost`
TRIGGER `testdb`.`insert_sample_auto_inc`
BEFORE INSERT ON `testdb`.`samples`
FOR EACH ROW
-- Edit trigger body code below this line. Do not edit lines above this one
BEGIN
SELECT COALESCE(MAX(`Sample ID`) + 1, 1) INTO @`Sample ID` FROM samples WHERE `Patient ID` = NEW.`Patient ID` AND `Test ID` = NEW.`Test ID`;
SET NEW.`Sample ID` = @`Sample ID`;
END
$$
delimiter ;
ケースで参照整合性を強制するために複合キーは必要ありません。その理由は、かなり単純な3層の階層があるためです。
PATIENT
+
|
^
TEST
+
|
^
SAMPLE
SAMPLE
テーブルにはTEST
テーブルへの単純な外部キーが必要であり、TEST
テーブルにはPATIENT
テーブルへの単純な外部キーが必要です。
これは、サンプルレコードごとにテストレコードが必要であり、テストごとに患者が必要であるため機能します。患者を削除する場合、そのテストはカスケード削除する必要があります。テストを削除する場合は、そのサンプルをカスケード削除する必要があります。したがって、patient_id
TEST
テーブル内。必要なのは、次のように外部キーのカスケード削除を宣言することだけです...
...
CONSTRAINT 'FK_TEST__PATIENT' FOREIGN KEY ('patient_id')
REFERENCES 'PATIENT' ('patient_id') ON DELETE CASCADE
...
CONSTRAINT 'FK_SAMPLE__TEST' FOREIGN KEY ('test_id')
REFERENCES 'TEST' ('test_id') ON DELETE CASCADE
...