我有两个表格,我们称之为Foo
和Bar
,其中Foo
是Bar
的父亲之间的一对多关系。 Foo的主键是使用序列自动生成的整数。
由于Bar
完全依赖于Foo
,如果给出以下约束,我将如何设置Bar
的主键:
Select Max()
生成一个ID
会
提出竞争条件。我想出了两个我不满意的可能解决方案:
FooID
和
FooBarID
并生成一个值
FooBarID
选择。{
某些max(FooBarID)+1
的{{1}},但是
如前所述,这创造了一个
竞争条件。我很欣赏任何替代表格布局的想法。
答案 0 :(得分:5)
为Bar提供与Foo相同的自动主键。将外键FooID列添加到Bar。
除非我遗漏某些东西,否则似乎没有理由说它不起作用。
答案 1 :(得分:3)
除非我在您的描述中遗漏了某些内容,否则这听起来像是一个普通的案例。通常的解决方案是这样的:
INSERT INTO Foo (foo_id, othercolumn)
VALUES ( FooSeq.NextVal(), 'yadda yadda');
INSERT INTO Bar (bar_id, foo_id, extracolumn)
VALUES ( BarSeq.NextVal(), FooSeq.CurrVal(), 'blah blah');
INSERT INTO Bar (bar_id, foo_id, extracolumn)
VALUES ( BarSeq.NextVal(), FooSeq.CurrVal(), 'bling bling');
INSERT INTO Bar (bar_id, foo_id, extracolumn)
VALUES ( BarSeq.NextVal(), FooSeq.CurrVal(), 'baz baz');
序列的CURRVAL()
函数仅返回当前会话期间序列生成的最新值。其他并发使用该序列不会影响会话中CURRVAL()
返回的内容。
答案 2 :(得分:0)
从你的描述中我假设你的数据库不支持自动增量标识符字段(MS SQL确实如此,Oracle有'序列',如果不是更好,那就好了,我不记得MySql了。) / p>
如果是,那么您只需要一个自动增量FooId和一个自动增量BarId,而Bar也有一个FooId作为外键
如果没有,那么您可以创建一个单行表进行分配,如下所示:
create table SystemCounter
(
SystemCounterId int identity not null,
BarIdAllocator int
)
--initialize SystemCounter to have one record with SystemCounterId = 1
--and BarIdAllocator = 0
insert into SystemCounter values (1,0)
--id allocator procedure
create procedure GetNextBarId ( @BarId int output ) AS
SET NOCOUNT ON
begin tran
update SystemCounter set
@BarId = BarIdAllocator = BarIdAllocator + 1
where SystemCounterId = 1
commit
GO
请注意,如果您的数据库不支持语法
@BarId = BarIdAllocator = BarIdAllocator + 1
然后你需要这样做而不是
begin tran
update SystemCounter set
BarIdAllocator = BarIdAllocator + 1
where SystemCounterId = 1
select
@BarId = BarIdAllocator
from SystemCounter
where SystemCounterId = 1
commit
编辑:我最初错过了Oracle标签,所以Bill的解决方案就是必要的。如果有人使用不支持身份或序列构造的数据库,请留下此答案作为如何执行此操作的示例
答案 3 :(得分:0)
根据Ant P和其他答案,我不能完全看到为什么只为bar生成一个唯一的ID并丢弃Foo的ID将无效。但假设您处于自动递增ID不可用的情况,那么有两个解决方案不涉及选择max(barid)+1
预先生成一个唯一ID表,并使用事务从表中提取下一个可用ID并将其删除(作为原子操作)。这样可以正常工作,但缺点是必须保持表格填充。
生成UUID作为主键。这通常不是一个好的选择,因为UUID对于此用途来说效率低,但它确实具有不需要额外的基础结构表的优点。 UUID生成器可以广泛使用,一些数据库内置它们。