微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使一列的约束值与另一列的约束值相同?

如何解决如何使一列的约束值与另一列的约束值相同?

TABLE 1 (photos)
photo_id | student_id | main_photo
----------------------------------
1        | 1          | 0
2        | 1          | 1
3        | 2          | 1
4        | 1          | 0 

我需要确保对于相同的student_id,只有一张主照片。因此,1的值只能是一个,并且不能为两个或多个(对于同一个student_id),但是0的值可以是多个(一个以上)。

MysqL版本:5.7

解决方法

您真正想要的是一个经过过滤的唯一索引。 MySQL,MySQL不允许这样做。

相反,您可以对生成的列使用技巧:

alter table photos add main_photo_null int generated always as
 (nullif(main_photo,0));

然后您可以在唯一约束中使用它:

create unique index unq_photos_main on photos(student_id,main_photo_null);

MySQL在唯一索引/约束中为NULL允许多个值,因此当main_photo值为0时,不强制执行唯一性。

Here是db 小提琴。

,

在最新的MySQL版本中,可以在唯一索引中使用case表达式:

create unique index idx_photos_uniq 
    on photos((case when main_photo then student_id end));

这在逻辑上为student_id的行上强制执行main_photo的唯一性(实际上假设这是一个布尔列-否则您可能想要when main_photo = 1)。

Demo on dB Fiddle

create table photos (
    photo_id int auto_increment primary key,student_id int,main_photo int
);

create unique index idx_photos_uniq 
    on photos((case when main_photo then student_id end));


insert into photos (student_id,main_photo) values (1,1);
insert into photos (student_id,0);
insert into photos (student_id,main_photo) values (2,0);
-- ok

insert into photos (student_id,1);
-- error: Duplicate entry '1' for key 'photos.idx_photos_uniq'
,

使用唯一的注解更改atbe,您将在下面看到结果

CREATE TABLE photos (
  `photo_id` INTEGER,`student_id` INTEGER,`main_photo` INTEGER
);
ALTER TABLE photos
ADD CONSTRAINT UC_student_id UNIQUE (student_id); 
INSERT INTO photos
  (`photo_id`,`student_id`,`main_photo`)
VALUES
  ('1','1','0')
INSERT INTO photos
  (`photo_id`,`main_photo`)
VALUES
  ('2','1')
  INSERT INTO photos
  (`photo_id`,`main_photo`)
VALUES
  ('3','2','1')
SELECT * FROM photos
photo_id | student_id | main_photo
-------: | ---------: | ---------:
       1 |          1 |          0
       3 |          2 |          1

db 提琴here

出于您的目的,您可以使用INSERT TRIGGER之前,它可以检查main_photo = 1

CREATE TABLE photos (
  `photo_id` INTEGER,`main_photo` INTEGER
);
#DELIMITER $$

CREATE TRIGGER before_photos_insert
BEFORE INSERT
ON photos FOR EACH ROW
BEGIN
    IF EXISTS(SELECT 1 FROM photos WHERE `main_photo` = 1 AND `student_id` = NEW.`student_id`) THEN
      SIGNAL sqlstate '45002' set message_text = 'mainphoto already exsits';
    END IF; 

END ;
#$$
#DELIMITER ;
INSERT INTO photos
  (`photo_id`,`main_photo`)
VALUES
  ('4','1')
mainphoto already exsits
SELECT * FROM photos
photo_id | student_id | main_photo
-------: | ---------: | ---------:
       1 |          1 |          0
       2 |          1 |          1
       3 |          2 |          1

db 提琴here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。