sql—在mysql数据库中添加约束以保证唯一性

luaexgnf  于 2021-06-20  发布在  Mysql
关注(0)|答案(4)|浏览(333)

我的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`)
  )

我想把姓氏放在这张简单的table上。为了做到这一点,我有一个微服务,调用者通过json发送家庭信息:

{
  "family_id" : 1,
  "names": ["name1", "name2"]
}

id是从mysql自动递增生成的。
因此,上面的json最终将触发两个insert语句:
插入(family\u id,name)值(1,name1)
插入(family\u id,name)值(1,name2)
当新请求带有表中存在的族标识时,就会出现问题。这应该是不允许的,我正在做一个查询,以搜索是否存在家庭\标识。如果存在,则引发异常。如何避免此查询?如果需要,可以更改表架构。如果a可以添加“请求id”或guid之类的内容来建立每个请求的唯一性,可以吗?
所有数据应在同一个表中。
下面是一个包含一些数据的表格示例

(来自注解)我无法创建第二个表。所有东西都应该放在一张table里。

fcg9iug3

fcg9iug31#

如果无法创建第二个表来正确建模约束,则必须采用序列化插入: LOCK TABLES new_table WRITE; 使用 SELECT 检查表中是否存在族id。
如果没有家庭身份证, INSERT 你的新数据。 UNLOCK TABLES; 有必要锁定表,否则将出现竞争条件。两个会话可以检查家族id是否存在,两个会话都发现它不存在,然后两个会话都继续执行它们的任务 INSERT . 如果锁定表,则一个会话将获取该锁并执行其工作,而另一个会话必须等待该锁,在获取该锁时,其检查将发现第一个会话已插入了族id。
这种方法通常被认为不利于并发性,如果您有许多请求,它会限制您的吞吐量。但是,如果请求不频繁,对吞吐量的影响将是最小的。

fcipmucu

fcipmucu2#

这是一个解决设计问题的方法,但我想我还是把它贴出来吧。您可以生成如下查询:

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

然后检查受影响的行数以确定它是否成功。

lskq00tm

lskq00tm3#

你需要两张table。

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 如果需要的话,两张table的位置?

6ju8rftf

6ju8rftf4#

您应该规范化您的模式并使用两个表。
家庭和(我猜)人。然后你可以用 UNIQUE 约束 family_id 并将族标识作为外键添加到person表中。

相关问题