1

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

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

4 回答 4

1

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

  1. 创建名称/昵称对表,
  2. INSERT INTO NicknameTable SELECT Nickname FROM temp WHERE Nickname NOT IN (SELECT Nickname FROM NicknameTable)
  3. 在知道昵称存在的情况下插入主表。

在您的示例中,您可以只拥有一个可为空的昵称列而没有另​​一个表,除非一个人可以拥有多个昵称。

于 2008-12-08T19:56:57.200 回答
0

说实话?我会在 Person 表中将昵称设为 varchar 列,而忘记 Nickname 表。昵称是一个人的属性,而不是一个单独的实体。

这是一个简化的例子,你的“标识符”真的实体关系中受益吗?

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

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

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

INSERT INTO Nickname (name) VALUES ("Bill")
  ON DUPLICATE KEY UPDATE name = name;
于 2008-12-08T20:05:03.080 回答
0
INSERT INTO Person(Name, NicknameID)
    VALUES(:name, (SELECT id FROM Nickname WHERE Name = :nickname))

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

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

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

于 2008-12-08T20:34:06.297 回答
0

或者,也许“合并”声明会有所帮助?它提供了插入新值或更新现有值的选项。语法和支持因数据库而异,但可能比“ON DUPLICATE”选项更常见。

于 2009-09-02T13:11:52.260 回答