2011-09-22 101 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');