Получение правильного автоматически увеличенного идентификатора в базе данных Oracle - PullRequest
2 голосов
/ 21 декабря 2010

Я вставляю одну строку в таблицу базы данных ORACLE, где ID первичного ключа - автоинкремент. а также Я извлекаю автоинкрементный идентификатор из этой таблицы.

В случае, если много людей используют один и тот же СТОЛ. Я могу столкнуться с проблемой потребительского производителя, где я могу получить идентификатор другого пользователя.

Некоторые пользователи SO упоминали о получении этих увеличенных идентификаторов. основан на соединении , которое не приведет к Consumer Producer проблема:

Просто хочу проверить ниже вещи с SO:

First:

Получу ли я точный автоинкрементный идентификатор из нижеуказанного сценария:

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 ]

4 голосов
/ 21 декабря 2010

Вы должны использовать возвращающее предложение:

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; 

Таким образом, вы получаете фактически вставленный идентификатор вместо необходимости запрашивать самый высокий идентификатор и надеяться, что он правильный.

2 голосов
/ 22 декабря 2010

Во-первых, не существует такого существа, как «автоинкрементный» идентификатор.У Oracle есть последовательности и триггеры.Можно использовать триггер для выбора значения последовательности при вставке.Oracle не гарантирует порядок в генерации последовательности, он не гарантирует, что значения не имеют пробелов.Это гарантирует, что вы получите уникальную ценность.Так что на самом деле нет запроса, который сообщит вам, какая последняя последовательность была добавлена ​​в таблицу.MAX может быть правильным, но более низкое число, извлеченное из буфера последовательности и задержанное перед вставкой, может появиться после более высокого числа.

Крейг имеет лучший ответ для правильного способа сделать это.Осталось обсудить ваши четыре сценария.

Вам нужно прочитать о ACID .

ACID (атомарность, согласованность, изоляция, долговечность)это набор свойств, которые гарантируют, что транзакции базы данных обрабатываются надежно.

В то время как в вашем коде могут быть проблемы с параллелизмом (т. е. условия гонки или не поточнобезопасные), базы данных не имеют таких проблем.(Не предполагается и обычно не делает) Хорошие базы данных разрабатываются с нуля, чтобы соответствовать требованиям ACID.Каждая транзакция изолирована от любой другой транзакции.Если вы вставите в эту таблицу и в той же транзакции выберите Max (ID), а я вставлю в эту таблицу и выберу MAX (ID) как часть моей одной транзакции, я увижу вставленный номер, а вы увидите вставленный номер.,Любая данная транзакция будет отображать только те данные, которые существовали на момент начала транзакции.

Вы можете переопределить эту функцию, изменив уровни изоляции, но ACID - это хорошо.Вы хотите это.Oracle работал именно так в течение длительного времени.

В плохо спроектированных базах данных изоляция осуществляется с помощью блокировок.Если вы читаете строку и держите транзакцию открытой, чтобы убедиться, что ваше следующее чтение совпадает, запрашиваемая строка блокируется.Это означает, что читатели могут блокировать авторов - плохо.В Oracle, начиная с версии 5 или 6, Oracle была в состоянии воссоздать представление данных в таблице, как они отображались в начале вашей транзакции, с помощью MultiVersion Concurrency Control .Это поведение по умолчанию в Oracle в течение двух десятилетий.Не каждая БД настолько продвинута ... убедитесь, что вы понимаете уровни изоляции, с которыми вы работаете, прежде чем делать НИЧЕГО в базе данных.

...