在表中插入与另一个表有关系的行

时间:2008-12-08 19:42:59

标签: database database-design jpa insert

在我的数据库模式中,我有一个已识别的实体。标识符可以重复使用,因此与实体存在一对多的关系。示例:一个人可以有一个昵称。昵称不是唯一的,可以在很多人之间共享。因此架构可能如下所示:

PERSON
id
name
nickname_id

NICKNAME
id
name

问题是,在插入新人时,我必须首先查询NICKNAME以查看昵称是否存在。如果没有,那么我必须在NICKNAME中创建一行。当插入许多人时,这可能会很慢,因为每个人插入都会导致查询NICKNAME

我可以通过首先查询所有昵称的昵称来优化大插入。 JPA查询语言:

SELECT n FROM NICKNAME n WHERE name in ('Krusty', 'Doppy', 'Flash', etc)

然后根据需要创建新的昵称,然后在人员上设置nickname_id。

这使得软件变得复杂,因为它必须暂时将昵称存储在内存中。此外,某些数据库对IN子句的参数有限制(SQL Server为2100左右),因此我执行了多次查询。

我很好奇其他人如何处理这个问题。更具体地,当数据库被规范化并且实体与另一个实体具有关系时,插入新实体基本上导致必须检查另一个实体。对于大型插入,除非将操作提升到代码域,否则这可能很慢。有没有办法自动插入相关的表行?

仅供参考我正在使用Hibernate的JPA实现

4 个答案:

答案 0 :(得分:1)

我不确定ORM是否可以处理这个问题,但是在直接SQL中你可以:

  1. 创建名称/昵称对的表格,
  2. INSERT INTO NicknameTable SELECT昵称FROM temp WHERE昵称NOT IN(SELECT Nickname FROM NicknameTable)
  3. 在知道昵称存在的情况下插入主表。
  4. 在您的示例中,除了一个人可以拥有多个昵称之外,您可以只使用另一个表中的NULLable昵称列。

答案 1 :(得分:0)

如实?我在昵称表中将昵称设为varchar列,并忘记了昵称表。昵称是一个人的属性,而不是一个单独的实体。

这是一个简化的示例,您的'标识符'真的从实体关系中受益吗?

编辑:好的,明白这只是一个人为的例子。这个问题很好,因为它经常出现。

标准SQL支持带有可选“...ON DUPLICATE KEY UPDATE...”子句的INSERT语句形式。对此语法的支持因数据库品牌而异。如果在Nickname表中为标识符名称添加UNIQUE约束,则重复的条目将调用该子句的UPDATE部分(您可以执行虚拟更新,而不是更改任何内容)。

CREATE TABLE Nickname (
  id SERIAL PRIMARY KEY,
  name VARCHAR(20) UNIQUE
);

INSERT INTO Nickname (name) VALUES ("Bill")
  ON DUPLICATE KEY UPDATE name = name;

答案 2 :(得分:0)

INSERT INTO Person(Name, NicknameID)
    VALUES(:name, (SELECT id FROM Nickname WHERE Name = :nickname))

如果INSERT由于昵称不存在而失败,则插入昵称,然后插入人员记录。

我假设:name和:nickname标识包含用户名和昵称的主机变量 - 并且当从SQL中省略该person.id列时,将自动为该person.id列分配值。适应您的情况。

如果您认为大多数昵称实际上都是唯一的,您可以简单地尝试无条件地插入昵称,但忽略昵称已经存在时发生的错误。

答案 3 :(得分:0)

或许,或许'MERGE'声明可能有帮助吗?它提供了插入新值或更新existsng值的选项。语法和支持因DB而异,但可能比'ON DUPLICATE'选项更常见。