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

标签 mysql sql

我有 PILOT1PILOT2 SIN 与 SHIP ID。 我不想要这个:

ship1   111 222 4   20  idk 23.33   gop

ship1   222 111 4   20  idk 23.33   gop

看看 shipID 是如何相同的以及相同的飞行员正在操作这艘船。我想要一种方法来限制这一点。这是有效的,因为飞行员 ID 不同:

ship1   111 222 4   20  idk 23.33   gop

ship1   232 111 4   20  idk 23.33   gop

 

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),
    CONSTRAINT check_pilots CHECK (pilot1_SIN != pilot2_SIN)
);

最佳答案

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

您可以按照@TheImpaler的建议使用BEFORE INSERT触发器

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

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

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

遗憾的是,这不会验证 pilot1 不等于 pilot2,我想你可以添加

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

但我不能 100% 确定它会被允许

注意 说了这么多,我发现在我的项目中总是存在数据库层无法轻松解决的验证问题。我很想在应用程序层验证这种情况。只要您只有一个代码区域可以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 名不同的飞行员

旁白

我还建议以下内容

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

关于mysql - 如何检查 SQL 表中是否存在一对。约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52748892/

相关文章:

sql - 如何在我的子选择中删除相关子查询(由于 presto 限制)

sql - "cannot perform a DML operation inside a query"的解决方案?

sql - 数字 ID 与字符串 ID

php - Codeigniter 设置横向数据库过滤器

mysql - 为什么MYSQL "NOT IN"对1亿条记录的操作不起作用?

mysql - 使用 group by 计算行数并显示所有行 MYSQL PHP

php - 检查表 A 中的特定条目是否存在于表 B 中,如果存在,则忽略这些值

php mySQL查询过程数组循环

sql - 如何用SQL语句计算百分比

sql - 如何在 SQL Server 2014 上启用 MSDTC?