我的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,
"names": ["name1", "name2"]
}
该ID是通过MySQL的自动递增生成的。
因此上述JSON将最终触发两个插入语句:
当新请求带有表中存在的family_id时,就会出现问题。这不应该被允许,我正在做一个查询以便搜索family_id是否存在。如果存在,则会引发异常。如何避免此查询?如果需要,可以更改表架构。如果可以添加诸如“请求ID”之类的内容,或为每个请求建立唯一性的向导,是否可以?
所有数据应在同一表上。
下面是带有一些数据的表格示例
(来自注释)我无法创建第二张表。一切都应该放在一张桌子上。
答案 0 :(得分:6)
您应该规范化架构并使用两个表。
家庭和(我假设)人。然后,您可以为UNIQUE
使用family_id
约束,并将family_id作为外键添加到Person表中。
答案 1 :(得分:3)
您需要两个表。
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"
);
PRIMARY KEY
是UNIQUE KEY
是KEY
。
您说您不能添加第二张表。但为什么?您提到需要生成特定的JSON吗?如果必要的话,不能简单地通过两个表中的JOIN
完成吗?
答案 2 :(得分:2)
如果您不能创建第二个表来正确地对约束进行建模,那么您将不得不求助于序列化插入:
LOCK TABLES new_table WRITE;
SELECT
检查表中是否存在家庭ID。INSERT
您的新数据。UNLOCK TABLES;
必须锁定表,因为否则您将出现竞争状况。两个会话可以检查家族ID是否存在,都发现它不存在,然后都以其INSERT
进行。如果您锁定表,则一个会话将获取该锁并执行其工作,而另一会话必须等待该锁,并且在获取该锁时,其检查将发现该家族ID已被插入。第一次会议。
通常认为这种方法不利于并发,如果有很多请求,这可能会限制吞吐量。但是,如果您的请求很少,那么对吞吐量的影响将很小。
答案 3 :(得分:0)
这是解决设计问题的方法,但我认为我不妨发布它。您可以生成如下查询:
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
然后检查受影响的行数,以确定是否成功。