如何检查SQL表中是否存在一对。约束

时间:2018-10-10 21:15:32

标签: mysql sql

我有PILOT1PILOT2的SIN对。 我不想要这样:

SHIP ID

查看ship1 111 222 4 20 idk 23.33 gop ship1 222 111 4 20 idk 23.33 gop 是如何相同的,并且相同的飞行员正在操作该船。我想要一种方法来约束这一点。这是有效的,因为飞行员ID不同:

shipID

ship1   111 222 4   20  idk 23.33   gop

ship1   232 111 4   20  idk 23.33   gop

3 个答案:

答案 0 :(得分:1)

不幸的是,正如@Barmar所指出的那样,即使在8.0版中,MySQL也完全忽略了任何CHECK CONSTRAINTS

您可以根据建议使用BEFORE INSERT触发器@TheImpaler

对于开箱即用的解决方案,您可以使用generated column

pilot_check_unique VARCHAR(23) AS (CONCAT(
  LEAST(pilot1_SIN,pilot2_SIN), ':', GREATEST(pilot1,pilot2) 
)) NOT NULL UNIQUE

如果表不是InnoDB,则必须通过将STORED放在STORED之前来创建列UNIQUE,这当然会增加表使用的磁盘空间

遗憾的是,这无法验证pilot1是否等于pilot2,我想您可以添加

pilot_check_not_equal TINYINT(1) AS (
  CASE WHEN pilot1_SIN != pilot2_SIN THEN 1 END CASE
) NOT NULL

但我不是100%肯定会允许使用

NB 说了这么多,我发现在我的项目中总是存在验证问题,这些问题在数据库层很难解决。我很想在应用程序层中验证这种情况。只要您只有INSERTUPDATE这段代码的一个区域,就可以了。

添加

另一种选择是将Ship表分为ShipShip_pilot

CREATE TABLE Ship (
    shipID varchar(30) NOT NULL,
    years_in_operation INT,
    num_of_seats INT,
    manufacturer varchar(30),
    advertising_revenue FLOAT,
    fuel_type varchar(15)
    PRIMARY KEY (shipID)
);

CREATE TABLE Ship_Pilot (
    shipID varchar(30) NOT NULL,
    pilot_SIN varchar(11) NOT NULL,
    position TINYINT(3) UNSIGNED NOT NULL
    PRIMARY KEY (shipID, pilot_SIN),
    FOREIGN KEY (pilot_SIN) REFERENCES Pilot(SINumber),
    UNIQUE KEY (shipID, position)
);

这不会重复您的船只飞行员或职位,但会允许您每艘船0-256位不同的飞行员

ASIDE

我还会建议以下内容

  • UNSIGNED整数类型用于ID
  • UNSIGNEDnum_of_seats使用years_in_operation整数,大概不能为负数
  • fuel_typemanufacturer中的每一个使用单独的表,并使用UNSIGNED整数引用它们,而不是重复名称
  • 您的船表有一个复合PK,这将允许同一张表中的shipID多次(有不同的飞行员)-正确吗?
  • 为精度DECIMAL使用advertising_revenue或整数类型

答案 1 :(得分:0)

您可以这样做:

CREATE TABLE Ship (
shipID varchar(30) NOT NULL,
pilot1_SIN varchar(11) NOT NULL,
pilot2_SIN varchar(11) NOT NULL,
years_in_operation INT,
num_of_seats INT,
manufacturer varchar(30),
advertising_revenue FLOAT,
fuel_type varchar(15)
PRIMARY KEY (shipID, pilot1_SIN, pilot2_SIN),
FOREIGN KEY (pilot1_SIN) REFERENCES Pilot(SINumber),
FOREIGN KEY (pilot2_SIN) REFERENCES Pilot(SINumber),
);

create unique index IX_Unique on (Ship (least(pilot1_SIN, pilot2_SIN), greatest(pilot1_SIN, pilot2_SIN)));

答案 2 :(得分:0)

这是另一个主意...

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table (id1 INT NOT NULL,id2 INT NOT NULL,PRIMARY KEY(id1,id2));

INSERT INTO my_table SELECT LEAST(4,9),GREATEST(4,9);

SELECT * FROM my_table;
+-----+-----+
| id1 | id2 |
+-----+-----+
|   4 |   9 |
+-----+-----+

INSERT INTO my_table SELECT LEAST(4,9),GREATEST(4,9);
ERROR 1062 (23000): Duplicate entry '4-9' for key 'PRIMARY'