如果列设置为 x,则 SQL 唯一约束

发布于 2024-10-13 04:23:02 字数 487 浏览 5 评论 0原文

如果特定列具有特定值,SQL 有没有办法创建列必须唯一的约束?

示例:这些行并未真正删除,而是在数据库中标记为“已删除”。在“未删除”行中,ValueA 必须是唯一的:

ID    ValueA          ValueB            Deleted
-----------------------------------------------------
1     'foo'           10               0
2     'bar'           20               0
3     'bar'           30               1
4     'bar'           40               1
5     'foo'           50               0 --NOT ALLOWED

我想到了类似 CHECK 约束的东西,但我不知道如何做到这一点。

is there a way in SQL to create the constraint that a column has to be unique, if a specific column has a specific value?

Example: the rows are not really deleted, but marked as 'deleted' in the database. And within the 'not-deleted' rows, ValueA has to be unique:

ID    ValueA          ValueB            Deleted
-----------------------------------------------------
1     'foo'           10               0
2     'bar'           20               0
3     'bar'           30               1
4     'bar'           40               1
5     'foo'           50               0 --NOT ALLOWED

I thought of something like a CHECK constraint, however I don't know how to do this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

迷爱 2024-10-20 04:23:02

对于 SQL92 这是不可能的,也许你可以用触发器实现一些东西

with SQL92 this is not possible, may be you could implement something with a trigger

三岁铭 2024-10-20 04:23:02

你能稍微改变一下设计吗?

在我看来,你有一份“东西”清单。对于每个 ValueA,在任何时候都有一个活动的“事物”。最好按如下方式建模:

  1. 从您的主 Thingies 表中删除 ValueA 和 Deleted。

  2. 创建一个包含 ValueA 和 ID 列的新表 ActiveThingies。通过将 ValueA 设置为唯一键或主键来保护此表。 (您可能还需要使 ID 唯一,具体取决于单个 ID 是否可以表示超过 1 个 ValueA)。

现在,使用 ActiveThingies 表随时控制哪条记录是当前的。要更改“foo”的活动(未删除)记录,请更新 ActiveThingies 中的 ID 列。

要获取未删除项目的列表,请连接两个表。

然而,通过这种设计,您将无法记住“已删除”“事物”的 ValueA。如果您需要记住这些值,您还需要在 Thingies 中包含 ValueA 列。

Can you change the design a little bit?

It seems to me that you have a list of "thingies". For each ValueA, there's a single active "thingy" at any one time. This can best be modeled as follows:

  1. Remove ValueA and Deleted from your main Thingies table.

  2. Create a new table ActiveThingies with columns ValueA and ID. Protect this table by making ValueA a unique or primary key. (You may also need to make ID unique as well depending on whether a single ID can represent more than 1 ValueA).

Now, use the ActiveThingies table to control which record is current at any time. To change the active (non-deleted) record for "foo", update it's ID column in ActiveThingies.

To get your list of non-deleted items join the two tables.

With this design, however, you will lose the ability to remember the ValueA for "deleted" "thingies". If you need to remember those values, you will also need to include the ValueA column in Thingies.

青衫负雪 2024-10-20 04:23:02

此问题有解决方法 - 创建另一个列 deleted_on

deleted_on 时间戳 NOT NULL DEFAULT '0000-00-00 00:00:00'

并在 ValueAdeleted_on 上创建唯一键

UNIQUE KEY not_deleted(ValueA,deleted_on)

软删除记录时插入 NOW() 作为 deleted_on 的值

There is workaround this problem - create another column deleted_on

deleted_on timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'

and make unique key on both ValueA and deleted_on

UNIQUE KEY not_deleted (ValueA, deleted_on)

When soft deleting a record insert NOW() for value of deleted_on

难得心□动 2024-10-20 04:23:02

MySQL 忽略 CHECK 约束,因此您无法像在其他数据库中那样在 MySQL 中执行此操作。

这是一个黑客。 valueA + 已删除的唯一约束。当删除行时,你不能只使用 1,它们必须是 1、2、3...

这至少可以让你在 MySQL 的服务器端执行此操作,但引入了一个步骤。当将一行标记为删除时,您必须首先找到最大值(已删除),加1,然后在标记为删除时插入该值。

MySQL ignores CHECK constraints, so you cannot do this in MySQL as you might in another database.

Here is a hack. Unique constraint on valueA + deleted. When deleting rows you cannot use just 1, they must be 1, 2, 3...

This at least lets you do it server-side in MySQL, but introduces a step. When marking a row for deletion, you have to first go find the max(deleted), add 1, and plug that value in when marking for deletion.

゛清羽墨安 2024-10-20 04:23:02

将表拆分为两个表:一张对 ValueA 有 UNIQUE 约束,另一张则没有。使用视图+触发器组合两个表。像这样的东西:(

CREATE TABLE _Active (
    ID       INTEGER,
    ValueA   VARCHAR(255) UNIQUE,
    ValueB   INTEGER
);

CREATE TABLE _Deleted (
    ID       INTEGER,
    ValueA   VARCHAR(255), /* NOT unique! */
    ValueB   INTEGER
);

CREATE VIEW Thingies AS
    SELECT ID, ValueA, ValueB, 0 AS Deleted FROM _Active
UNION ALL
    SELECT ID, ValueA, ValueB, 1 AS Deleted FROM _Deleted;

CREATE TRIGGER _trg_ii_Thingies_Active
    INSTEAD OF INSERT ON Thingies
    FOR EACH ROW WHEN NOT NEW.Deleted
BEGIN
    INSERT INTO _Active(ID, ValueA, ValueB)
        VALUES (NEW.ID, NEW.ValueA, NEW.ValueB);
END;

CREATE TRIGGER _trg_ii_Thingies_Deleted
    INSTEAD OF INSERT ON Thingies
    FOR EACH ROW WHEN NEW.Deleted
BEGIN
    INSERT INTO _Deleted(ID, ValueA, ValueB)
        VALUES (NEW.ID, NEW.ValueA, NEW.ValueB);
END;

/* Add triggers for DELETE and UPDATE as appropriate */

我不确定 CREATE TRIGGER 语法,但你知道我的意思。)

Split your table into two tables: One which has a UNIQUE constraint on ValueA and one that doesn't. Use a view+triggers to combine the two tables. Something like:

CREATE TABLE _Active (
    ID       INTEGER,
    ValueA   VARCHAR(255) UNIQUE,
    ValueB   INTEGER
);

CREATE TABLE _Deleted (
    ID       INTEGER,
    ValueA   VARCHAR(255), /* NOT unique! */
    ValueB   INTEGER
);

CREATE VIEW Thingies AS
    SELECT ID, ValueA, ValueB, 0 AS Deleted FROM _Active
UNION ALL
    SELECT ID, ValueA, ValueB, 1 AS Deleted FROM _Deleted;

CREATE TRIGGER _trg_ii_Thingies_Active
    INSTEAD OF INSERT ON Thingies
    FOR EACH ROW WHEN NOT NEW.Deleted
BEGIN
    INSERT INTO _Active(ID, ValueA, ValueB)
        VALUES (NEW.ID, NEW.ValueA, NEW.ValueB);
END;

CREATE TRIGGER _trg_ii_Thingies_Deleted
    INSTEAD OF INSERT ON Thingies
    FOR EACH ROW WHEN NEW.Deleted
BEGIN
    INSERT INTO _Deleted(ID, ValueA, ValueB)
        VALUES (NEW.ID, NEW.ValueA, NEW.ValueB);
END;

/* Add triggers for DELETE and UPDATE as appropriate */

(I'm not sure about the CREATE TRIGGER syntax, but you know what I mean.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文