在MySQL数据库中添加约束以保证唯一性

在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

我的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最终将触发两个insert语句:

  • 插入(族id,名称)值(1,名称1)
  • 插入(族id,名称)值(1,名称2)
当新请求带有表中存在的族id时,就会出现问题。这是不允许的,我正在执行一个查询,以搜索该族id是否存在。如果存在,则引发异常。我怎样才能避免这个问题?如果需要,可以更改表架构。如果a可以添加“请求id”或guid之类的内容来建立每个请求的唯一性,可以吗

所有数据应在同一个表中

下面是包含一些数据的表格示例


(来自注释)我无法创建第二个表。所有内容都应该保存在一个表中。

您应该规范化您的模式并使用两个表

家庭和(我假设)个人。然后,您可以对家庭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触发器。