#sql #oracle
#sql #Oracle
Вопрос:
Я должен менять номера рейсов для пар рейсов, следующих туда и обратно из набора городов, так, например:
1439 ATL SFO
1440 SFO ATL
в конечном итоге будет выглядеть:
1440 ATL SFO
1439 SFO ATL
Я попробовал этот запрос (потому что вы не можете ОБНОВИТЬ .. ПРИСОЕДИНИТЬСЯ в Oracle):
UPDATE
(SELECT f.airline, f.flightno flightno_f, d.airline, d.flightno flightno_d
FROM flights f
INNER JOIN flights d ON f.airline = 9 AND
f.sourceairport = d.destairport AND
f.destairport = d.sourceairport AND d.airline = 9
WHERE d.flightno < f.flightno) g
SET g.flightno_f = g.flightno_d,
g.flightno_d = g.flightno_f;
где airline, flightno является первичным ключом для таблицы рейсов. Выбор дает мне правильный набор записей, на которые я хочу поменять местами, но ОБНОВЛЕНИЕ… SET выдает мне эту ошибку:
SET g.flightno_f = g.flightno_d,
*
ERROR at line 7:
ORA-01779: cannot modify a column which maps to a non key-preserved table
Есть идеи о том, где я ошибаюсь?
Комментарии:
1. @therin Попробуйте добавить ограничение изменить таблицу рейсов, добавить ограничение flights_uk unique (flightno);
2. Добавить ограничение к созданному мной представлению g? Я не уверен, что вы имеете в виду. Я попытался добавить другое ограничение в таблицу рейсов, но одна из других основных проблем, с которыми я столкнулся, заключается в том, что я не могу добавить уникальное ограничение только для номера рейса, может быть идентичный номер рейса для другой авиакомпании.
3. @therin Это проблема, с которой вы сталкиваетесь, поскольку у вас идентичный номер рейса, который он не может обновить
4. @Sam: это один из обязательных шагов. Но другой шаг — написать запрос (вложенный select), который возвращает однозначный результирующий набор.
5. Это то, о чем я думал изначально, но когда я на самом деле выполняю запрос, повторяющихся номеров рейсов нет , потому что я отфильтровываю их все. Есть ли какой-либо ручной способ обойти это?
Ответ №1:
Для обновления соединения не имеет значения, что выбранный вами набор данных фактически сохранен с ключом; Oracle должен иметь возможность видеть из ограничений и предикатов, что он по определению будет сохранен с ключом. И поскольку у вас есть условие неравенства для flightnumber, в определении данных нет ничего, что гарантировало бы, что у вас не будет нескольких совпадений для данной исходной строки.
Если гарантировано, что номера рейсов всегда будут отличаться на 1, вы могли бы использовать метод join, если измените условие на d.flightno 1 = f.flightno
.
В любом случае, я думаю, что сработает следующее … из-за согласованности чтения на уровне оператора подзапрос должен возвращать правильные результаты даже при обновлении строк.
UPDATE flights f1
SET flightno =
(SELECT flightno
FROM flights f2
WHERE f2.airline = f1.airline
AND f2.sourceairport = f1.destairport
AND f2.destairport = f1.sourceairport
)
WHERE airline = 9;