質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

2回答

1316閲覧

INSERT時のチェック制約について

yakan

総合スコア19

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

0クリップ

投稿2020/06/29 08:58

MySQL5.7で、チェック制約を実現したいです。

こちらのページを拝読しますと、チェック制約の式はSELECT時と同じに見えました。

なので以下CONSTRAINT check_fks CHECK ()# 三つのうちどれか一つだけという制約をかけてみました。

SQL

1CREATE TABLE mytable4 ( 2 ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 3 name VARCHAR(10), 4 PRIMARY KEY (ID) 5); 6 7CREATE TABLE mytable3 ( 8 ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 9 number INT(3), 10 PRIMARY KEY (ID) 11); 12 13CREATE TABLE mytable2 ( 14 ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 15 address VARCHAR(10), 16 PRIMARY KEY (ID) 17); 18 19CREATE TABLE IF NOT EXISTS mytable1 ( 20 ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 21 mytable2_ID INT(10) UNSIGNED, # どれか一つだけ入る 22 mytable3_ID INT(10) UNSIGNED, # どれか一つだけ入る 23 mytable4_ID INT(10) UNSIGNED, # どれか一つだけ入る 24 PRIMARY KEY (ID), 25 FOREIGN KEY (mytable2_ID) REFERENCES mytable2(ID), 26 FOREIGN KEY (mytable3_ID) REFERENCES mytable3(ID), 27 FOREIGN KEY (mytable4_ID) REFERENCES mytable4(ID), 28 CONSTRAINT check_fks CHECK ( 29 # 三つのうちどれか一つだけという制約 30 (mytable2_ID IS NOT NULL) AND (mytable3_ID IS NULL) AND (mytabl4_ID IS NULL) OR 31 (mytable2_ID IS NULL) AND (mytable3_ID IS NOT NULL) AND (mytabl4_ID IS NULL) OR 32 (mytable2_ID IS NULL) AND (mytable3_ID IS NULL) AND (mytabl4_ID IS NOT NULL) 33 ) 34);

しかし以下で、mytable1の3行目のレコードのINSERTで、( 3,1,NULL )と指定しており、つまりmytable2_IDmytable3_IDの二つに値を入れてしまっており、これは制約に違反するためにエラーにしたいのですが、普通に成功してしまいます。

SQL

1INSERT INTO mytable4 ( name ) 2VALUES ( 'Steve' ),( 'Rob' ),( 'Eric' ); 3 4INSERT INTO mytable3 ( number ) 5VALUES ( 100 ),( 200 ),( 300 ); 6 7INSERT INTO mytable2 ( address ) 8VALUES ( 'a' ),( 'b' ),( 'c' ); 9 10INSERT INTO mytable1 ( mytable2_ID, mytable3_ID, mytable4_ID ) 11VALUES ( 1,NULL,NULL ),( NULL,2,NULL ),( 3,1,NULL ); 12# ( 3,1,NULL ) というINSERTは制約に違反するためエラーにしたい

どのようにすれば# 三つのうちどれか一つだけという制約の部分の制約はうまくいきますでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

対応方法

次のいずれかの対応を行います:

  • MySQL のバージョンを8.0.16 以降に上げます
  • MySQL 以外で CHECK 句が有効なデータベースを使います
  • アプリケーション側で値をバリデーションします

解説

参照された記事は MySQL に限定した内容の記事ではないようです:

SQLの制約の種類とその指定方法 - Qiita

MySQL 5.7 では CHECK 句はまだ実装されていないようです:

MySQL :: MySQL 5.7 Reference Manual :: 13.1.18 CREATE TABLE Statement

CHECK
The CHECK clause is parsed but ignored by all storage engines.

MySQL 8.0.16 以降であれば CHECK 句は機能するようです:

MySQL :: MySQL 8.0 Reference Manual :: 13.1.20.6 CHECK Constraints

Prior to MySQL 8.0.16, CREATE TABLE permits only the following limited version of table CHECK constraint syntax, which is parsed and ignored:

参考: Answer: CHECK constraint in MySQL is not working

投稿2020/06/29 09:24

y_shinoda

総合スコア3272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yakan

2020/06/29 09:30

詳細なリンク助かります。どうもありがとうございました。ひとまずアプリケーション側で対処します。
guest

0

ベストアンサー

残念ながら、MySQLにCHECK制約が実装されたのは、MySQL 8.0.16以上です(公式リファレンス)。

それ未満のMySQLでもテーブル作成時にCHECK制約を設定することはできますが、ただ無視されます

投稿2020/06/29 09:03

編集2020/06/29 09:05
maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yakan

2020/06/29 09:05

そうでしたか。残念ですが納得できました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問