我有发票表。它有很多领域,但问题是2个主要领域
我们的业务要求InvoiceNo是独一无二的。但是,如果删除了一行,我们可以重新使用InvoiceNo
InvoiceNo Deleted
123Er 1
123Er 0
以上是有效的用例。但我不想再与123Er& 0
是否可以为特定值的2个字段组合创建唯一键唯一(InvoiceNo,Deleted = 0)还是应该用于存储过程还是触发器?
答案 0 :(得分:2)
在function based index的帮助下,很容易在其他RDBMS系统中实现
至于现在MySql没有这样的功能,但从版本5.7开始,可以使用虚拟(或生成)列进行模拟。
简单的工作示例:http://rextester.com/HGY68688
CREATE TABLE IF NOT EXISTS mytable1234(
InvoiceNo varchar(10),
Deleted int,
xxx varchar(10) generated always as (case when deleted = 0 then InvoiceNo end) virtual
);
create unique index myindex12 on mytable1234( xxx );
INSERT INTO mytable1234( InvoiceNo, Deleted) VALUES ('aaa1', 0 );
INSERT INTO mytable1234( InvoiceNo, Deleted) VALUES ('aaa1', 1 );
INSERT INTO mytable1234( InvoiceNo, Deleted) VALUES ('aaa1', 1 );
-- INSERT INTO mytable1234( InvoiceNo, Deleted) VALUES ('aaa1', 0 );
如果您取消注释此代码段中的最后一个INSERT,然后尝试运行此代码段,则会出现Duplicate entry 'aaa1' for key 'myindex12'
错误。
通过这种方式,表中可能有多条记录InvoiceNo
的{{1}}值相同,但deleted = 1
只有一个值,因为MySql不允许这样做。
答案 1 :(得分:2)
您可以将字段重命名为DeletedIfNull
(或IsActive
)。
然后,该字段将取值" 1"或"真"或者无论列是否有效。对于任何其他值,它将是NULL
。然后你可以创建:
create unique index unq_t_invoiceno_isactive on t(invoiceno, isactive);
MySQL(尽管不是所有数据库)在定义唯一索引时允许重复。因此,这将解决您当前的问题。
答案 2 :(得分:0)
你可以创建一个唯一的密钥(InvoiceNo,Deleted),并完成它。我不明白为什么你需要制作(InvoiceNo,Deleted = 0),这是不受支持的。拥有这两列的唯一键可以满足您的需求。
更新: 我遇到了你的问题,你可能有两个相同值的删除行。在这种情况下,我建议您将某些添加到已删除值的InvoiceNo列中,以便它们不会是唯一的。
例如: 您有 123er 然后删除它,因此它变为 123er-1 。当您删除另一个时,它将变为 123er-2 。你甚至可以在更新(之前)触发器中完成它。