Mysql唯一约束允许组合的单行

时间:2016-06-24 14:51:40

标签: mysql unique-constraint

是否可以使用唯一约束,使一个特定列只有一次值?

例如

-----------------------    
name | price | default
-----------------------
XYZ  |  20   | TRUE
-----------------------
XYZ  |  30   | FALSE
-----------------------
XYZ  |  40   | FALSE
-----------------------
ABC  | 50    | FALSE
-----------------------

因此,在上表中,对于特定的name值,default值只能为TRUE一次。名字和名称将有一个独特的约束价格列。

这可能吗?

5 个答案:

答案 0 :(得分:1)

我用一个奇怪的aproch解决了这个问题,使用TIMESTAMP作为标志。

那是用作" 已删除" FLAG。

如果IS为NULL,则寄存器未被删除 - 相反,如果删除(<> NULL),则唯一密钥永远不会发生冲突,从而避免重复寄存器为非扩展的已删除寄存器。

例如在您的情况下:

您永远不会有2行默认值:NULL ,但您可以使用 N TIMESTAMP 并排除时间。

答案 1 :(得分:1)

你可以制作一个触发器来检查是否已经有一个' TRUE'价值,如果采取行动。

请注意,您不能轻易地拒绝"更新。 (参见例如:How to abort INSERT operation in MySql trigger?)。

例如,您可以使用false插入它,并通过设置标志以某种方式保存您的错误。

答案 2 :(得分:1)

在所有三列上放置一个简单的唯一约束是行不通的,因为它允许以下内容:

name | price | default
-----------------------
XYZ  |  20   | TRUE
XYZ  |  30   | TRUE
XYZ  |  40   | FALSE
ABC  |  50   | FALSE

在其他SQL引擎中,您可以创建一个检查约束,确保对于每组name行,default = TRUE行的数量是< = 1.但是,MySQL确实不支持强制检查约束。

在MySQL中,您可以通过insertupdate触发器实现此目的:

CREATE TRIGGER `before_insert` BEFORE INSERT ON `tableName`
FOR EACH ROW
BEGIN

   DECLARE @sum INT

   SELECT @sum = SUM(CASE WHEN [default] = TRUE THEN 1 ELSE 0 END)
   FROM tableName
   WHERE [name] = new.[name]

   IF (@sum = 0 OR new.default = FALSE)
   BEGIN
      INSERT INTO tableName (name, price, default)
      VALUES (new.[name], new.[price], new.[defaul]t)

   END
END

同样适用于update

答案 3 :(得分:1)

normal方法是提取一个单独的表来保存默认价格:

CREATE TABLE price (
    name VARCHAR(255),
    price INT,
    PRIMARY KEY (name, price)
) ;

CREATE TABLE defaultPrice (
    name VARCHAR(255),
    price INT,
    PRIMARY KEY (name),
    FOREIGN KEY(name, price) REFERENCES price(name, price)
);

大多数人会建议引入代理键:

CREATE TABLE item (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    UNIQUE(name)
);

CREATE TABLE price (
    itemId INT,
    price INT,
    PRIMARY KEY (itemId, price),
    FOREIGN KEY (itemId) REFERENCES item (id)
) ;

CREATE TABLE defaultPrice (
    itemId INT,
    price INT,
    PRIMARY KEY (itemId),
    FOREIGN KEY (itemId, price) REFERENCES price (itemId, price)
);

答案 4 :(得分:0)

这是一种可能适合您需求的解决方法。请考虑以下表定义和唯一约束:

SELECT t1.*, t2.`Linked CODE`
FROM yourTable t1
LEFT JOIN yourTable t2 ON t2.`Product CODE` = t1.`Linked CODE`
WHERE t1.`Product CODE` = 'BI DS110';

在您的应用层中,当CREATE TABLE prices ( id int NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL, price int, default varchar(255) ) ALTER TABLE prices ADD UNIQUE idx (id, name, default); INSERT defaultFALSE进行记录时,请始终离开idNULL。这将导致MySQL始终为id添加唯一值,以便可以输入namedefault的重复值(即default值{{1}对于给定的FALSE,可能会多次出现。

但是,当name INSERTdefault的记录为TRUE时,您应始终使用相同的 id值。这样可以确保给定的name只能显示TRUE一次。