jur*_*iks 9 mysql null unique-constraint
CREATE TABLE IF NOT EXISTS b2c_constants (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64) NOT NULL,
is_deleted BOOL DEFAULT FALSE,
UNIQUE (name)
) ENGINE InnoDB CHARSET utf8 COLLATE utf8_unicode_ci
CREATE TABLE IF NOT EXISTS b2c_constant_bindings (
constant_id INT UNSIGNED NOT NULL,
company_id INT UNSIGNED NOT NULL,
object_id INT UNSIGNED DEFAULT NULL,
property_id INT UNSIGNED DEFAULT NULL,
value VARCHAR(255) NOT NULL,
UNIQUE (constant_id, company_id, object_id, property_id),
FOREIGN KEY (constant_id) REFERENCES b2c_constants (id) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (company_id) REFERENCES companies (id) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (object_id) REFERENCES b2b_objects (id) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (property_id) REFERENCES b2b_properties (id) ON UPDATE RESTRICT ON DELETE CASCADE
) ENGINE InnoDB CHARSET utf8 COLLATE utf8_unicode_ci
Run Code Online (Sandbox Code Playgroud)
问题在于bindings
表中的唯一键。如果我有这样的数据:
constant_id company_id object_id property_id value
1 1 null null foo
1 1 1 null bar
1 1 1 1 baz
Run Code Online (Sandbox Code Playgroud)
可以无限复制前两行而没有任何错误,这显然是不可取的。
这种结构的想法是允许全局绑定每个公司、公司中的每个对象和公司中的每个属性的常量,但只允许为这些中的每一个绑定唯一的常量。
有没有办法在数据库中解决这个问题,同时保持外键和简单的表结构?我知道我可以做type ENUM ('company', 'object', 'property'), type_id INT
,但是我丢失了外键以及所有常量所需的公司 ID。
Jeh*_*aki 12
[这没有经过测试,因为它需要 MySQL 5.7.6 或更高版本]
虽然我同意上面的评论,但我仍然有一个可以尝试的想法,我认为这在性能方面不是最好的,但它解决了您所描述的问题。
这个想法是添加一个NULL
作为具体值处理的键,如“0”或任何其他值。然后,对要唯一的字段组合进行唯一索引。
MySQL 5.7.6 支持生成列。
ALTER TABLE b2c_constant_bindings
ADD unique_md5 char(32) AS
(MD5(CONCAT_WS('X', ifnull(constant_id, 0), ifnull(company_id, 0), ifnull(object_id, 0), ifnull(property_id,0))))
UNIQUE;
Run Code Online (Sandbox Code Playgroud)
CONCAT
我没有使用CONCAT_WS
,而是用来避免在类似于CONCAT(1, 23)
和的情况下出现相同的结果CONCAT(12, 3)
(根据@Rick James 的通知,ss)。