Вставить в Oracle неправильный путь - как с этим бороться? - PullRequest
0 голосов
/ 19 февраля 2009

Я только что нашел следующий код:

select max(id) from TABLE_NAME ...

... do some stuff ...

insert into TABLE_NAME (id, ... )
VALUES (max(id) + 1, ...)

Я могу создать последовательность для PK, но есть куча существующего кода (классический asp, существующие приложения asp.net, которые не являются частью этого проекта), который не собирается его использовать.

Стоит ли просто игнорировать это или есть способ исправить это, не вдаваясь в существующий код?

Я думаю, что лучший вариант просто сделать:

insert into TABLE_NAME (id, ... )
VALUES (select max(id) + 1, ...)

Опция

Ответы [ 6 ]

2 голосов
/ 19 февраля 2009

Вы можете создать триггер в таблице, который перезаписывает значение для ID значением, которое вы выбираете из последовательности. Таким образом, вы все равно можете использовать другой существующий код и не иметь проблем с одновременными вставками.

Если вы не можете изменить другое программное обеспечение, и оно по-прежнему делает выбор вставки max (id) +1, что является самым неудачным. Что вы можете сделать, это:

Для вашей собственной вставки используйте последовательность и заполните поле идентификатора -1 * (значение последовательности). Таким образом, вставка не будет мешать существующим программам, но также не будет конфликтовать с существующими программами. (сделать вставку без значения для идентификатора и использовать триггер, чтобы заполнить идентификатор отрицательным значением последовательности).

1 голос
/ 20 февраля 2009

Это быстро переходит к обсуждению архитектуры приложения, особенно когда вопрос сводится к "что мне делать?"

Первичные ключи в Oracle действительно должны происходить из последовательностей, и, поскольку вы имеете дело со сложной логикой вставки (родительские / дочерние вставки, по крайней мере) в коде приложения, вы должны войти в существующий код, как вы говорите триггеры, вероятно, вам не помогут).

С одной стороны, вы можете отобрать прямой доступ к SQL из приложений и заставить их вызывать службы, чтобы код вставки / обновления / удаления мог быть централизованным. Или вы можете переписать свой код, используя некую архитектуру MVC. Я предполагаю, что оба излишни для вашей ситуации.

Установлен ли по крайней мере столбец id как истинный первичный ключ, поэтому существует ограничение, которое будет препятствовать возникновению дубликатов? Если нет, начните там.

Как только первичный ключ установлен, или, если он уже есть, вставки начинают выходить из строя; вы будете знать, когда они начнут терпеть неудачу, верно? Если нет, включите регистрацию ошибок.

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

1 голос
/ 19 февраля 2009

Используйте последовательность в триггере строки перед вставкой. select max (id) + 1 не работает в многоконкурентной среде.

1 голос
/ 19 февраля 2009

Как уже говорили другие, вы можете переопределить максимальное значение в триггере базы данных, используя последовательность. Однако это может вызвать проблемы, если какой-либо код приложения использует это значение следующим образом:

select max(id) from TABLE_NAME ...

... do some stuff ...

insert into TABLE_NAME (id, ... )
VALUES (max(id) + 1, ...)

insert into CHILD_TABLE (parent_id, ...)
VALUES (max(id) + 1, ...)
0 голосов
/ 18 февраля 2013

Это можно сделать, выбрав максимальное значение в переменной, а затем просто вставив его в таблицу, как

Declare v_max int; выберите max (id) в v_max из таблицы;

вставка в таблицу значений ((v_max + rownum), val1, val2 ...., valn); совершить;

Это создаст последовательность в одиночном и групповом вставках.

0 голосов
/ 19 февраля 2009

Большой вопрос: кто-нибудь полагается на стоимость ПК? Если нет, я бы порекомендовал использовать триггер, получить идентификатор из последовательности и установить его. Вставки не будут указывать и идентификатор вообще.

Я не уверен, но

вставить в TABLE_NAME (id, ...) ЗНАЧЕНИЯ (выберите max (id) + 1, ...)

может вызвать проблемы, когда сеансы достигают этого кода. Возможно, оракул читает таблицу (вычисляя max (id)), а затем пытается получить блокировку PK для вставки. В этом случае два одновременных сеанса могут попытаться использовать один и тот же идентификатор, что вызовет исключение во втором сеансе.

Вы можете добавить запись в триггер, чтобы проверить, обрабатываются ли вставки, для которых уже установлен идентификатор. Итак, вы знаете, что вам все еще нужно искать какое-то место, где используется старый код.

...