В Oracle 10g нам нужно вставлять записи из представления в таблицу, чтобы поддерживать тупое клиентское приложение, которое само не имеет опций сортировки или ORDER. Есть ли способ контролировать порядок, в котором наш оператор INSERT добавляет записи в целевую таблицу?
INSERT с ORDER в Oracle
- Зачем тебе это надо? Есть ли какой-то триггер, который что-то делает при вставке? 27.08.2009
- Связано с stackoverflow.com/questions/ 33841234/ 21.07.2016
- @zendar Если это похоже на то, что мне нужно было сделать с таблицей «Страны», у кого-то могут быть записи, которые будут привязаны к раскрывающемуся списку или списку на веб-странице, и желательно, чтобы все они были в алфавитном порядке по имени, а не в числовом порядке по ID, и иметь новые записи, которые были добавлены задним числом или из-за текущих событий и вышли из строя, требуя перекодирования страниц для отсортированных раскрывающихся списков/списков, когда вместо этого вы можете просто исправить это в базе данных. 21.07.2016
- @vapcguy прочитайте первую строку выбранного ответа - без ORDER BY вы не можете знать, в каком порядке Oracle будет возвращать записи, даже если вы вставите их в отсортированном порядке. Ответу семь лет, и он все еще в силе. 23.07.2016
- @zendar Вы не можете знать, в каком порядке Oracle будет возвращать записи, даже если вы вставите их в отсортированном порядке - Б.С. Как насчет того, чтобы попробовать мой ответ, который я разместил ниже. Вы были против? Я доказал, что могу это сделать. Да,
ORDER BY
не применяется к обычномуINSERT
. Добавьте подсказку/*+APPEND*/
из принятого ответа (который он отклонил, поэтому я проголосовал за него и добавил свой собственный пример, где это сработало) и вуаля, это работает! Вот почемуORDER BY
существует в первую очередь - если вы добавляете строки в том порядке, в котором они были найдены, именно так вы контролируете свои вставки. 25.07.2016 - @zendar И почему он отклонил это, так это из-за любого DML или параллельной активности ... может привести к другой физической организации. Хотя, возможно, это так, но когда вы когда-нибудь будете настолько глупы, чтобы сделать это и разрушить свой собственный код, выполняя параллельную деятельность?! Вот почему я не выполняю параллельные операции и использую в своем коде оператор
COMMIT
, так что этого не происходит! 25.07.2016
Ответы:
Вы не можете не надежно контролировать, в каком порядке Oracle извлекает строку таблицы без ORDER BY
.
Кроме того, без подсказки /*+APPEND*/
Oracle будет физически хранить строки в таблице кучи, где есть место, которое может не находиться в конце таблицы! Вы можете подумать, что Oracle вставляет их последовательно, но любое DML или параллельное действие (вставка 2+ сеансов) может привести к другой физической организации.
Вы можете использовать таблицу INDEX ORGANIZED хранить строки в порядке ПК. После этого большинство простых запросов к этой таблице создадут отсортированный набор строк. Однако это не гарантирует, что оракул выберет строки именно в таком порядке, если вы не укажете ORDER BY (в зависимости от запроса и пути доступа строки могут располагаться в любом порядке).
Вы также можете использовать представление с порядком, это, вероятно, ваш лучший выбор, если вы не можете коснуться приложения (переименуйте таблицу, создайте представление с именем таблицы, пусть приложение думает, что оно запрашивает таблицу). Не знаю, возможно ли это в вашем случае.
Если вы не укажете ORDER BY, вы никогда не сможете гарантировать порядок, в котором Oracle будет возвращать строки из SELECT.
Просто используйте ORDER BY. Что-то типа
INSERT INTO table
(
SELECT
column1, column2
FROM
view
ORDER BY
column2
)
РЕДАКТИРОВАТЬ, на самом деле это не сработает. Вы можете создать временное представление со строками в соответствующем порядке, а затем выполнить вставку.
Ваша основная проблема, связанная с тем, что ваше приложение не добавляет ORDER BY к своему запросу, возможно, может быть решена путем использования индекса в столбцах, которые вы хотите упорядочить, а затем использовать сохраненную схему, чтобы заставить запрос использовать индекс для доступа к таблице.
Вам нужно будет проверить, будет ли это работать или нет - имейте в виду, что, возможно, недостаточно просто добавить подсказку INDEX(), потому что оптимизатор может найти способ соблюдать подсказку, не обращаясь к индексу в правом заказ; и если запрос соединяется с другими таблицами, порядок может быть потерян в любом случае.
ДА, ЕСТЬ способ контролировать ваш заказ. По опыту я обнаружил, что у меня была таблица стран, назовем ее OLD_COUNTRIES
, которая выглядела так:
-----------------------------------
| ID | CODE | NAME |
-----------------------------------
|112099 | AF | Afghanistan |
|112100 | AA | Albania |
|... | .. | ... |
|112358 | ZB | Zimbabwe |
|112359 | AZ | Azores Islands |
|... | .. | ... |
-----------------------------------
Где я хотел, чтобы элементы, которые были добавлены после основного списка стран (например, Азорские острова и другие острова, которые были добавлены позже), действительно отображались в алфавитном порядке с остальными странами, когда я вставлял их в новую таблицу:
CREATE TABLE MYAPP.COUNTRIES
(
ID NUMBER(*, 0)
, CODE NVARCHAR2(20)
, NAME NVARCHAR2(250)
);
Затем я запустил это, чтобы заставить его работать:
INSERT /*+ append */ INTO MYAPP.COUNTRIES (ID, CODE, NAME)
SELECT ID, CODE, NAME FROM MYAPP.OLD_COUNTRIES_TABLE ORDER BY NAME ASC;
COMMIT;
И моя новая таблица COUNTRIES
отлично прошла по алфавиту по именам.
ПРИМЕЧАНИЕ: COMMIT
требуется, иначе вы получите сообщение об ошибке: ORA-12838: cannot read/modify an object after modifying it in parallel
при попытке открыть таблицу для просмотра в Oracle SQL Developer.
ПРИМЕЧАНИЕ. Если вы не используете /*+ append */
, он не будет вставляться в указанном вами порядке — он будет игнорировать ORDER BY
. И я знаю, что он использовал мой ORDER BY
, когда я использовал /*+ append */
, а не просто по умолчанию использовал первичный ключ для старой или новой таблицы, потому что ни у одной из них не было первичных ключей.
ПРЕДОСТЕРЕЖЕНИЕ: по словам автора принятого ответа, добавление подсказки, как и в случае с «любым DML или параллельным действием... может привести к другой физической организации». Хотя, возможно, это так, не выполняйте никаких параллельных операций во время этого и используйте оператор COMMIT
в своем коде там, где я это делаю, чтобы этого не произошло!
2 + 2
равно 4
, прибавление любого целого числа к самому себе всегда равно 4
. 21.03.2019
/*+APPEND*/
, а не просто намекнуть на нее, а потом отмахнуться. Это на самом деле ответ о том, как это сделать! Работал нормально для меня! 20.07.2016