在Oracle DB中获取正确的自动递增ID

时间:2010-12-21 15:16:11

标签: c# database oracle primary-key

我在ORACLE数据库表中插入一行,其中 主键ID是自动增量。 和 我正从该TABLE中重新获取自动增量ID。

如果有很多人使用相同的TABLE。 我可能会遇到消费者生产者问题 获取其他用户的ID。

SO上的一些用户提到了获取这些递增的ID 基于connection,不会导致消费者制作人 问题:

只想用SO来检查下面的内容:

首先

我是否会从下面的sceneario获得确切的自动增量ID:

1) Two computer with in different subnet using DB.
2) Two computer wiht in same subnet using DB.
3) Two process using using DB connection.
4) Two thread uisng DB connection.

第二

 If my insert is:
 Insert into Tables (ID,NAME,DESCRIPTION) values (DBNull,'Name','Description');

 What should be my query to get the autoincremented ID generated for above
 Insert.

C# related command will do much help :)

2 个答案:

答案 0 :(得分:4)

你应该使用return子句:

declare
    v_id TABLES.ID%TYPE;
begin
    Insert into Tables (ID,NAME,DESCRIPTION)
    values (seq.nextval,'Name','Description')
    RETURNING id INTO v_id;
--
    dbms_output.put_line(v_id);
end; 

通过这种方式,您可以获得实际插入的ID,而不必重新查询最高ID,并希望它是正确的ID。

答案 1 :(得分:2)

首先,没有“自动增量”ID这样的生物。 Oracle具有序列和触发器。可以使用触发器在插入时选择序列值。 Oracle不保证顺序生成中的顺序,它不保证值没有间隙。它确保您获得独特的价值。因此,实际上没有任何查询可以告诉您最后一个序列添加到表中的内容。 MAX可能是正确的,但是从序列的缓冲区中提取的较低数字和在插入之前延迟的数字可能会在更高的数字后显示。

克雷格有正确的方法来做到这一点。遗漏的是对你的四种情景的讨论。

您需要阅读ACID

  

ACID(原子性,一致性,   隔离,耐久性)是一套   保证数据库的属性   交易得到可靠处理。

尽管您的代码可能存在并发问题(即竞争条件或非线程安全),但数据库不存在此类问题。 (不应该而且通常不会)良好的数据库是从头开始设计的,以满足ACID的需求。每笔交易都与其他交易隔离。如果您插入该表并在同一事务中选择Max(ID)并插入该表并选择MAX(ID)作为我的一个事务的一部分,我将看到我插入的数字,您将看到插入的数字。任何给定的交易将仅显示交易开始时存在的数据。

您可以通过更改隔离级别来覆盖此功能,但ACID是一件好事。你要这个。 Oracle长期以来一直如此工作。

在设计不佳的数据库中,隔离是通过锁完成的。如果您读取一行并保持事务处于打开状态,为了确保您的下一次读取是相同的,您要求的行将被锁定。这意味着读者可以阻止作家 - 这是一件坏事。在Oracle中,从版本5或6开始,Oracle已经能够通过MultiVersion Concurrency Control重新创建表中数据的视图,因为它在事务开始时出现。这已成为Oracle 20年来的默认行为。并非每个数据库都是如此先进...确保您在数据库中执行任何操作之前了解您正在使用的隔离级别。