J'ai des problèmes avec cette table
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))
);
Je veux avoir une contrainte de clé étrangère, et cela fonctionne. Ensuite, je veux ajouter une contrainte à l'attribut status
afin qu'il ne puisse prendre que les valeurs "a", "d" et "u". Il m'est impossible de définir le champ sur Enum
ou set
.
Quelqu'un peut-il me dire pourquoi ce code ne fonctionne pas dans MySQL?
Les contraintes CHECK
ne sont pas supportées par MySQL. Vous pouvez les définir, mais ils ne font rien (à partir de MySQL 5.7).
De la manuel :
La clause
CHECK
est analysée mais ignorée par tous les moteurs de stockage.
La solution consiste à créer des déclencheurs , mais ce n’est pas la chose la plus facile à utiliser.
Si vous voulez un SGBDR open-source prenant en charge les contraintes CHECK
, essayez PostgreSQL . C'est en fait une très bonne base de données.
Je ne comprends pas pourquoi personne ici n'a mentionné que VIEW WITH CHECK OPTION peut être une bonne alternative au CHECK CONSTRAINT dans MySQL:
CREATE VIEW name_of_view AS SELECT * FROM your_table
WHERE <condition> WITH [LOCAL | CASCADED] CHECK OPTION;
Il y a un doc sur le site MySQL: La clause View WITH CHECK OPTION
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');
P.S .: N'oubliez pas que votre vue doit pouvoir être mise à jour! Voir Vues modifiables MySQL (Merci à Romeo Sierra pour les précisions apportées dans les commentaires).
En plus des déclencheurs, pour des contraintes simples comme celle que vous avez:
CONSTRAINT `participants_ibfk_2`
CHECK status IN ('a','d','u')
vous pouvez utiliser un Foreign Key
de status
dans une table de référence (ParticipantStatus
avec 3 lignes: 'a','d','u'
):
CONSTRAINT ParticipantStatus_Participant_fk
FOREIGN KEY (status)
REFERENCES ParticipantStatus(status)
Voici un moyen d'obtenir les chèques que vous vouliez rapidement et facilement:
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);