2011-09-22 99 views
24

我无法与此表如何向表中添加检查约束?

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'。我不能将字段设置为Enumset

谁能告诉我为什么这段代码在MySQL中不起作用吗?

回答

54

CHECK约束不受MySQL支持。你可以定义它们,但它们什么也不做(如MySQL 5.7)。

manual

CHECK子句解析,但所有的存储引擎忽略。

解决方法是创建triggers,但它们不是最简单的工作。

如果您想要一个支持CHECK约束条件的开源​​RDBMS,请尝试PostgreSQL。它实际上是一个非常好的数据库。

+0

谢谢你的短期和具体的答案 –

+11

有时候,我不知道为什么有人使用MySQL了 - “哎呀,对不起,我们决定不来实现数据的完整性!”。如果你对RDBMS有任何控制,并且你想要开源,Postgres就是The Way。 – Jordan

+0

的确如此。 由于众多原因,MySQL不是一个好的选择,这是其中之一。 – Dmitri

10

除了触发器,对于像一个简单的限制,你必须:

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

你可以使用一个Foreign Keystatus的参考表(ParticipantStatus 3行:'a','d','u'):

CONSTRAINT ParticipantStatus_Participant_fk 
    FOREIGN KEY (status) 
    REFERENCES ParticipantStatus(status) 
+1

谢谢你的建议。 –

-1

以下是一种快速方便地获得所需支票的方法:

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); 
8

我不明白,为什么这里没有人提到,WITH CHECK OPTION VIEW可以在MySQL的一个很好的替代CHECK约束

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');