40

このテーブルに問題があります

CREATE TABLE `Participants` (
  `meetid` int(11) NOT NULL,
  `pid` varchar(15) NOT NULL,
  `status` char(1) DEFAULT NULL,
  PRIMARY KEY (`meetid`,`pid`),
  CONSTRAINT `participants_ibfk_1` FOREIGN KEY (`meetid`) REFERENCES `Meetings` (`meetid`) ON DELETE CASCADE
  CONSTRAINT `participants_ibfk_2` CHECK (status IN ('a','d','u'))
  CONSTRAINT `participants_ibfk_3` CHECK (pid IN (SELECT name FROM Rooms) OR pid IN (SELECT userid FROM People))
);

私は外部キー制約を持ちたいのですが、それはうまくいきます。次に、属性に制約を追加してstatus、値「a」、「d」、および「u」のみを取得できるようにします。Enumフィールドをまたはとして設定することはできませんset

このコードが MySQL で機能しない理由を誰か教えてもらえますか?

4

5 に答える 5

79

CHECK制約は MySQL ではサポートされていません。それらを定義することはできますが、何もしません (MySQL 5.7 以降)。

マニュアルから:

句は解析されますが、CHECKすべてのストレージ エンジンによって無視されます。

回避策はトリガーを作成することですが、トリガーを使用するのは簡単ではありません。

CHECK制約をサポートするオープンソースの RDBMS が必要な場合は、 PostgreSQLを試してください。実際、これは非常に優れたデータベースです。

于 2011-09-22T22:07:18.707 に答える
19

VIEW WITH CHECK OPTIONがMySQLのCHECK CONSTRAINTの優れた代替手段になる可能性があるとここで誰も言及していない理由がわかりません。

CREATE VIEW name_of_view AS SELECT * FROM your_table
WHERE <condition> WITH [LOCAL | CASCADED] CHECK OPTION;

MySQL サイトにドキュメントがあります: The View WITH CHECK OPTION Clause

DROP TABLE `Participants`;

CREATE TABLE `Participants` (
  `meetid` int(11) NOT NULL,
  `pid` varchar(15) NOT NULL,
  `status` char(1) DEFAULT NULL check (status IN ('a','d','u')),
  PRIMARY KEY (`meetid`,`pid`)
);

-- should work
INSERT INTO `Participants` VALUES (1,1,'a');
-- should fail but doesn't because table check is not implemented in MySQL
INSERT INTO `Participants` VALUES (2,1,'x');

DROP VIEW vParticipants;
CREATE VIEW vParticipants AS 
  SELECT * FROM Participants WHERE status IN ('a','d','u')
  WITH CHECK OPTION;

-- should work
INSERT INTO vParticipants VALUES (3,1,'a');
-- will fail because view uses a WITH CHECK OPTION
INSERT INTO vParticipants VALUES (4,1,'x');

PS:ビューは更新可能である必要があることに注意してください。MySQL の更新可能なビューを参照してください (コメントで説明してくれた Romeo Sierra に感謝します)。

于 2017-03-13T10:55:21.400 に答える
15

トリガーのほかに、あなたが持っているような単純な制約の場合:

CONSTRAINT `participants_ibfk_2` 
  CHECK status IN ('a','d','u')

Foreign Keyfromstatusから参照テーブル ( ParticipantStatus3 行: 'a','d','u')を使用できます。

CONSTRAINT ParticipantStatus_Participant_fk
  FOREIGN KEY (status)
    REFERENCES ParticipantStatus(status) 
于 2011-09-22T23:20:57.930 に答える
0

必要なチェックをすばやく簡単に取得する方法は次のとおりです。

drop database if exists gtest;

create database if not exists gtest;
use gtest;

create table users (
  user_id       integer unsigned not null auto_increment primary key,
  username      varchar(32) not null default '',
  password      varchar(64) not null default '',
  unique key ix_username (username)
) Engine=InnoDB auto_increment 10001;

create table owners (
  owner_id      integer unsigned not null auto_increment primary key,
  ownername     varchar(32) not null default '',
  unique key ix_ownername (ownername)
) Engine=InnoDB auto_increment 5001;

create table users_and_owners (
  id    integer unsigned not null primary key,
  name  varchar(32) not null default '',
  unique key ix_name(name)
) Engine=InnoDB;

create table p_status (
  a_status      char(1) not null primary key
) Engine=InnoDB;

create table people (
  person_id integer unsigned not null auto_increment primary key,
  pid       integer unsigned not null,
  name      varchar(32) not null default '',
  status    char(1) not null,
  unique key ix_name (name),
  foreign key people_ibfk_001 (pid) references users_and_owners(id),
  foreign key people_ibfk_002 (status) references p_status (a_status)
) Engine=InnoDB;

create or replace view vw_users_and_owners as
select 
  user_id id,
  username name
from users
union
select 
  owner_id id,
  ownername name
from owners
order by id asc
;

create trigger newUser after insert on users for each row replace into users_and_owners select * from vw_users_and_owners;
create trigger newOwner after insert on owners for each row replace into users_and_owners select * from vw_users_and_owners;

insert into users ( username, password ) values
( 'fred Smith', password('fredSmith')),
( 'jack Sparrow', password('jackSparrow')),
( 'Jim Beam', password('JimBeam')),
( 'Ted Turner', password('TedTurner'))
;

insert into owners ( ownername ) values ( 'Tom Jones'),( 'Elvis Presley'),('Wally Lewis'),('Ted Turner');

insert into people (pid, name, status) values ( 5001, 'Tom Jones', 1),(10002,'jack Sparrow',1),(5002,'Elvis Presley',1);
于 2015-09-18T08:36:37.140 に答える