如果列设置为 x,则 SQL 唯一约束
如果特定列具有特定值,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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
对于 SQL92 这是不可能的,也许你可以用触发器实现一些东西
with SQL92 this is not possible, may be you could implement something with a trigger
你能稍微改变一下设计吗?
在我看来,你有一份“东西”清单。对于每个 ValueA,在任何时候都有一个活动的“事物”。最好按如下方式建模:
从您的主 Thingies 表中删除 ValueA 和 Deleted。
创建一个包含 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:
Remove ValueA and Deleted from your main Thingies table.
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.
此问题有解决方法 - 创建另一个列 deleted_on
deleted_on 时间戳 NOT NULL DEFAULT '0000-00-00 00:00:00'
并在 ValueA 和 deleted_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 ofdeleted_on
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.
将表拆分为两个表:一张对 ValueA 有 UNIQUE 约束,另一张则没有。使用视图+触发器组合两个表。像这样的东西:(
我不确定 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:
(I'm not sure about the CREATE TRIGGER syntax, but you know what I mean.)