【问题标题】:Insert 3 levels in one query在一个查询中插入 3 个级别
【发布时间】:2013-09-27 04:51:07
【问题描述】:

我有一个这样的 Oracle 数据结构:

俱乐部

Id
Name

一个俱乐部可以有很多支球队:

团队

Id
Name
ClubId

一个团队可以有很多玩家:

玩家

Id
Name
TeamId

如何插入包含有球员的球队的俱乐部?如果只是一个有球队的俱乐部,我可以这样做:

Insert all 
into Clubs (Id, Name) Values (ClubIdSequence.nextval,'Manchester United')
into Teams (Name, ClubId) Values ('A-Team',ClubIdSequence.currval)
into Teams (Name, ClubId) Values ('B-Team',ClubIdSequence.currval)
Select * from dual

但是我该如何插入播放器呢?

不起作用

Insert all 
into Clubs (Id, Name) Values (ClubIdSequence.nextval,'Manchester United')
into Teams (Id,Name, ClubId) Values (TeamIdSequence.nextval,'A-Team',ClubIdSequence.currval)
into Players (Name,Teamid) Values ('Michael Laudrup',TeamIdSequence.currval
into Teams (Id,Name, ClubId) Values (TeamIdSequence.nextval,'B-Team',ClubIdSequence.currval)
into Players (Name,Teamid) Values ('Brian Laudrup',TeamIdSequence.currval)
Select * from dual

因为

An UPDATE or INSERT statement attempted to insert a duplicate key.
        For Trusted Oracle configured in DBMS MAC mode, you may see
        this message if a duplicate entry exists at a different level

【问题讨论】:

  • 对不起,如果这听起来很愚蠢,但是查询不起作用是因为您错过了第 4 行和第 6 行的 ')' 吗?
  • 不,不是这样,Vaibhav - 但感谢您指出:)
  • 错误是什么?我怀疑这与序列有关。
  • 谢谢弗洛林 - 当然我应该添加错误消息。
  • 您还可以在表定义的同时添加约束.. 它似乎有一些约束违规。添加约束(如果有)(特别是唯一约束)

标签: sql oracle sql-insert


【解决方案1】:

这是一个需要 ClubIdSequence.nextval 和 TeamIdSequence.nextval 的语句。正在检索这些值,然后执行该语句。因此,您会得到两个具有相同 id 的团队。

使用您的第一个语句,您甚至可以交换 currval 和 nextval:

Insert all 
into Clubs (Id, Name) Values (ClubIdSequence.currval,'Manchester United')
into Teams (Name, ClubId) Values ('A-Team',ClubIdSequence.nextval)
into Teams (Name, ClubId) Values ('B-Team',ClubIdSequence.currval)
Select * from dual

还是一样:执行 nextval,然后使用 currval 进行插入。

在使用从序列中获取的 id 时,我强烈建议编写插入前触发器,以读取适当序列的 nextval 并填充 id。因此,插入语句的编写者不必找到相应的序列,因此在选择一个时不会出错。也有人可能会想用 id = max(id) + 1 编写插入语句,而忽略了甚至要使用序列这一事实。

一旦您使用触发器,您只需在插入语句中省略 id。

这仍然不能解决您的问题,因为您必须使用 currval,即使在一个语句中多次使用它也会给出相同的值。 (奇怪的是,它甚至在第一个插入语句之后为您提供了当前值,即既不是两个插入之前的那个也不是两个插入之后的那个,正如人们所期望的那样。)

所以你最终会遇到两种情况:要么使用序列而不使用全部插入,要么使用全部插入而不使用序列。他们只是相处得不好。

这是一个不使用序列的解决方案:

Insert all 
  into Clubs (id, Name) Values (max_id + 1, 'Manchester United')
  into Teams (Name, ClubId) Values ('A-Team',max_id + 1)
  into Clubs (id, Name) Values (max_id + 2, 'Manchester Apart')
  into Teams (Name, ClubId) Values ('B-Team',max_id + 2)
Select nvl(max(id),0) max_id from clubs

全部插入 进入俱乐部(名称)价值观(“曼联”) 进入团队(名称,ClubId)值('A-Team',max_id+1) 进入俱乐部(名称)价值观('Manchester Apart') 进入团队(名称,ClubId)值('B-Team',max_id+2) 从俱乐部中选择 max(id) max_id

【讨论】:

  • 抱歉回复晚了 - 在 Goto 会议上忘记了:-/ 担心是这样的(不可能)谢谢你的回答
猜你喜欢
  • 2017-05-11
  • 2021-10-02
  • 2011-04-21
  • 2013-11-20
  • 2016-04-30
  • 1970-01-01
  • 2015-05-02
相关资源
最近更新 更多