字段特定值对表的唯一约束
Unique constraint on tables for particular values of a field
我有发票table。它有很多领域,但问题是围绕2个主要领域
- InvoiceNo - 字母数字值
- Deleted - 布尔值 1 或 0,代表一条记录是否被删除。
我们的业务要求 InvoiceNo 是唯一的。但是,如果删除一行,我们可以重新使用 InvoiceNo
InvoiceNo Deleted
123Er 1
123Er 0
以上是一个有效的用例。但我不想再有 123Er & 0 的记录。
是否可以在 2 个字段的组合上为某些值 Unique(InvoiceNo,Deleted=0)创建唯一键,还是我们应该使用存储过程或触发器?
您只需创建一个唯一键(InvoiceNo、Deleted),即可完成。我不明白你为什么要制作 (InvoiceNo, Deleted=0),这是不支持的。拥有这两列的唯一键可以满足您的需求。
更新:
我遇到了你的问题,你可能有 2 个相同值的已删除行。在这种情况下,我建议您将 something 添加到已删除值的 InvoiceNo 列中,这样它们就不会是唯一的。
例如:
你有123er,然后删除它,所以它变成了123er-1。当你删除另一个时,它变成123er-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'
错误。
这样,table中可能会有多条记录,deleted = 1
的值相同,InvoiceNo
,而deleted = 0
的值只有一条,因为MySql会不允许这样。
您可以将字段重命名为 DeletedIfNull
(或 IsActive
)。
然后,如果该列处于活动状态,该字段将采用值“1”或 "true" 或其他任何值。对于任何其他值,它将是 NULL
。然后你可以创建:
create unique index unq_t_invoiceno_isactive on t(invoiceno, isactive);
MySQL(虽然不是所有数据库)在定义唯一索引时允许重复。因此,这将解决您眼前的问题。
我有发票table。它有很多领域,但问题是围绕2个主要领域
- InvoiceNo - 字母数字值
- Deleted - 布尔值 1 或 0,代表一条记录是否被删除。
我们的业务要求 InvoiceNo 是唯一的。但是,如果删除一行,我们可以重新使用 InvoiceNo
InvoiceNo Deleted
123Er 1
123Er 0
以上是一个有效的用例。但我不想再有 123Er & 0 的记录。
是否可以在 2 个字段的组合上为某些值 Unique(InvoiceNo,Deleted=0)创建唯一键,还是我们应该使用存储过程或触发器?
您只需创建一个唯一键(InvoiceNo、Deleted),即可完成。我不明白你为什么要制作 (InvoiceNo, Deleted=0),这是不支持的。拥有这两列的唯一键可以满足您的需求。
更新: 我遇到了你的问题,你可能有 2 个相同值的已删除行。在这种情况下,我建议您将 something 添加到已删除值的 InvoiceNo 列中,这样它们就不会是唯一的。
例如: 你有123er,然后删除它,所以它变成了123er-1。当你删除另一个时,它变成123er-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'
错误。
这样,table中可能会有多条记录,deleted = 1
的值相同,InvoiceNo
,而deleted = 0
的值只有一条,因为MySql会不允许这样。
您可以将字段重命名为 DeletedIfNull
(或 IsActive
)。
然后,如果该列处于活动状态,该字段将采用值“1”或 "true" 或其他任何值。对于任何其他值,它将是 NULL
。然后你可以创建:
create unique index unq_t_invoiceno_isactive on t(invoiceno, isactive);
MySQL(虽然不是所有数据库)在定义唯一索引时允许重复。因此,这将解决您眼前的问题。