在MySQL数据库中添加约束以保证唯一性
我的SQL表具有以下DDL在MySQL数据库中添加约束以保证唯一性,mysql,sql,database,Mysql,Sql,Database,我的SQL表具有以下DDL CREATE TABLE `new_table` ( `id` int(11) NOT NULL AUTO_INCREMENT, `family_id` int(11) NOT NULL, `name` varchar(45) NOT NULL, PRIMARY KEY (`id`) ) 我想把姓氏放在这个简单的表格里。为了做到这一点,我有一个微服务,调用者通过JSON发送家庭详细信息: { "family_id" : 1, "name
CREATE TABLE `new_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`family_id` int(11) NOT NULL,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
)
我想把姓氏放在这个简单的表格里。为了做到这一点,我有一个微服务,调用者通过JSON发送家庭详细信息:
{
"family_id" : 1,
"names": ["name1", "name2"]
}
id是从MySQL自动递增生成的
因此,上面的JSON最终将触发两个insert语句:
- 插入(族id,名称)值(1,名称1)
- 插入(族id,名称)值(1,名称2)
(来自注释)我无法创建第二个表。所有内容都应该保存在一个表中。您应该规范化您的模式并使用两个表 家庭和(我假设)个人。然后,您可以对家庭id使用
唯一的约束,并将家庭id作为外键添加到Person表中。您需要两个表
CREATE TABLE Families (
family_id MEDIUMINT UNSIGNED AUTO_INCREMENT,
...
PRIMARY KEY(family_id)
);
CREATE TABLE FamilyNames (
family_id MEDIUMINT UNSIGNED, -- not auto-inc here
name VARCHAR(66) NOT NULL,
...
PRIMARY KEY(family_id, name) -- note "composite"
);
主键
是唯一键
是键
您说您不能添加第二个表。但是为什么呢?您提到需要生成特定的JSON吗?如果需要,难道不能通过两个表的连接来完成吗?如果不能创建第二个表来正确建模约束,则必须采用序列化插入:
锁定新表\u表写入代码>
使用选择
检查表中是否存在族id
如果族id不存在,请插入新数据
解锁表代码>
有必要锁定表,否则您将有一个竞争条件。两个会话可以检查族id是否存在,都发现它不存在,然后都继续执行其插入操作。如果锁定表,则一个会话将获取锁并执行其工作,而另一个会话必须等待锁定,在获取锁时,其检查将发现第一个会话已插入族id
这种方法通常被认为不利于并发性,如果您有许多请求,它会限制您的吞吐量。但是,如果请求不频繁,对吞吐量的影响将是最小的。这是一个解决设计问题的方法,但我想我还是发布它为好。您可以生成如下查询:
INSERT INTO `new_table` (`family_id`, `name`)
SELECT * FROM (
SELECT 1, 'name1'
UNION ALL
SELECT 1, 'name2'
) x
LEFT JOIN `new_table` n ON n.family_id = 1
WHERE n.family_id IS NULL
然后检查受影响的行数以确定是否成功。我无法创建第二个表。所有的东西都应该放在一张桌子上。对不起,我不得不在这个问题上提一下。但是我明白了您的意思。@cateof在这种情况下,如果族id已经存在,您不能使用传统约束,也不能避免在插入之前进行检查。@cateof还提到族id是通过MySQL中的自动增量生成的。这意味着您实际上拥有johannesp建议的族表-这是生成自动增量的表。另外,如果请求使用MySQL生成的autoincrement,为什么您可以有另一个具有相同家族id值的请求?@Shadow家族id不是自动生成的。@当然,您应该将其规范化为两个表。如果不是,您只是在处理数据库设计不好的症状。您编写了无法将其拆分为两个表的代码。你会使用触发器吗?对此有一个简洁的解决方案。@N.B.,可以使用yes触发器。