Oracle sql вставить если не существует
Я хочу сделать вставку SQL, если запись еще не существует.
Чтобы завершить оператор вставки, я должен получить некоторую информацию с помощью выбора вставки.
На входе у меня есть:
Во вставке я должен заполнить другое поле значениями, извлеченными с помощью вставки select.
Обычно я должен сделать:
1 - выберите с помощью where and state=1 и, если не существует, мне придется сделать вставку SQL
2- если запись не существует, получить значения полей code1 and code2 when >
3- сделать вставку
Можно ли сделать все за один запрос?
если еще не существует:
Можно ли объединить в одном запросе?
4 ответа
Способ сделать это с помощью одного оператора в Oracle - использовать оператор MERGE. В вашем случае вы бы сделали что-то вроде:
Вы можете использовать * волшебную подсказку Oracle IGNORE_ROW_ON_DUPKEY_INDEX для этого. Подсказка молча пропускает дублированную вставленную строку - обычно это приводит к `ORA-00001: ограничение уникальности (. ) нарушено.
Я предполагаю следующую настройку таблицы:
Так что теперь вы хотите игнорировать вставку с ключом 1 и выполнить вставку с ключом 2 с использованием code с записи со статусом 'b'
Это должно дать вам представление о том, как действовать:
Настройте подзапрос, чтобы получить code1 а также code2 по мере необходимости - вы можете использовать max(code1) и игнорировать status ,
Используйте переменную связывания, чтобы передать id (три раза) в запросе.
Ты можешь использовать insert . . . select :
Но если вы "действительно" хотите проверить перед вставкой, вы можете попробовать блок PL/SQL.
PL/SQL
ПРИМЕЧАНИЕ: убедитесь, что у вас есть / в конце. Это запустит ваш блок PL/SQL.
В основном этот блок пытается выбрать строку с заданным id , Если существует, просто нормально завершает блок. Если строки не возвращаются, то это "исключение" для блока, и вы "обрабатываете" его, вставляя то, что вам нужно.
По-другому
ПРИМЕЧАНИЕ. Если вы хотите увидеть какой-либо вывод блока PL/SQL, вам может потребоваться set serveroutput on; перед запуском любого блока PL/SQL.
Мне нужно иметь возможность запускать запрос Oracle, который идет, чтобы вставить несколько строк, но он также проверяет, существует ли первичный ключ, и если да, то он пропускает эту вставку. Что-то вроде:
возможно ли это вообще с Oracle?
бонусные баллы, если вы можете сказать мне, как это сделать в PostgreSQL или MySQL.
оператор называется MERGE. Посмотри, я слишком ленив.
остерегайтесь, однако, что слияние не является атомарным, что может вызвать следующий эффект (спасибо, Мариус):
SESS2: insert into t1 values(2, 2);
поздно пришел на вечеринку, но.
С oracle 11.2.0.1 есть семантический намек что можно сделать это: IGNORE_ROW_ON_DUPKEY_INDEX
обновление: хотя эта подсказка работает (если правильно пишется), есть лучше всего подходит которые не требуют Oracle 11R2:
первый подход-прямой перевод выше смысловой подсказка:
второй aproach-a много быстрее, чем оба выше подсказки, когда есть много разногласий:
это только вставляет, если вставляемый элемент еще не присутствует.
работает так же, как:
может быть не очень красиво, но это удобно:)
мы можем объединить двойной и не существует, чтобы архивировать ваше требование:
Если вы не хотите объединяться из другой таблицы, а скорее вставлять новые данные. Я придумал это. Может быть, есть лучший способ сделать это?
Это код на клиенте, тогда у вас есть много поездок на сервер, чтобы устранить это.
вставьте все данные в таблицу temportary, скажем T с той же структурой, что и myFoo
Это должно работать и на других базах данных - я сделал это на Sybase
это не самое лучшее, если очень мало новых данных будет вставлено, поскольку вы скопировали все данные по проводу.
я использовал код выше. Это долго, но, просто и сработало для меня. Похоже на код Майкла.
Это ответ на комментарий, опубликованный erikkallen:
вам не нужна временная таблица. Если вы есть только несколько строк, (выберите 1 из двойное соединение выберите 2 от двойного) будет делать. Почему ваш пример дает Ора-0001? Не сольют взять обновить блокировку на ключе индекса, а не продолжайте, пока Sess1 либо фиксация или откат? – erikkallen
Ну, попробуйте сами и скажите, получаете ли вы ту же ошибку, или не:
SESS2: insert into t1 values(2, 2);
Если ваша таблица "независима" от других (я имею в виду, что она не вызовет каскадного удаления или не установит отношения внешних ключей к нулю), хорошим трюком может быть сначала удалить строку, а затем вставить ее снова. Это могло бы выглядеть так:
удалить из MyTable, где prop1 = 'aaa'; / / предполагая, что он выберет не более одной строки!
Какой самый простой способ вставить строку, если она не существует, в PL/SQL (Oracle)?
Я хочу что-то вроде:
Но это не работает.
Примечание: эта таблица имеет 2 поля, скажем, name и age . Но только имя это ПК.
Предполагая, что вы на 10g, вы также можете использовать оператор MERGE. Это позволяет вставить строку, если она не существует, и игнорировать строку, если она существует. Люди склонны думать о MERGE, когда хотят сделать «upsert» (INSERT, если строка не существует, и UPDATE, если строка существует), но часть UPDATE теперь является необязательной, поэтому ее также можно использовать здесь.
Если имя PK, просто вставьте и поймайте ошибку. Причина, по которой это делается, а не любая проверка, заключается в том, что он будет работать даже при одновременной вставке нескольких клиентов. Если вы проверяете, а затем вставляете, вы должны удерживать блокировку в течение этого времени или ожидать ошибки в любом случае.
Код для этого будет что-то вроде
Используя части ответа @benoit, я буду использовать это:
Извините за то, что я не использую полный ответ, но мне нужна проверка IF , потому что мой код намного сложнее, чем этот пример таблицы с полями name и age. Мне нужен очень четкий код. Ну, спасибо, я многому научился! Я приму ответ @benoit.
Я обнаружил, что примеры немного сложны для ситуации, когда вы хотите убедиться, что в целевой таблице есть строка (особенно, когда у вас есть два столбца в качестве первичного ключа), но первичного ключа там вообще не может быть, поэтому ничего нет выбирать.
Вот что сработало для меня:
- Оператор SELECT внутри блока USING всегда должен возвращать строки. Если в этом запросе не возвращены строки, они не будут вставлены или обновлены. Здесь я выбираю из DUAL , поэтому всегда будет ровно одна строка.
- Условие ON - это то, что устанавливает критерии для сопоставления строк. Если у ON нет совпадения, выполняется оператор INSERT.
- Вы также можете добавить предложение WHEN MATCHED THEN UPDATE , если вы хотите больше контролировать обновления.
В дополнение к идеальным и действительным ответам, приведенным до сих пор, есть также подсказка ignore_row_on_dupkey_index , которую вы можете использовать:
Подсказка описана на Таити .
Вы можете использовать этот синтаксис:
если его открыть поп для запроса «введите переменную подстановки», используйте это перед запросами выше:
CTEи толькоCTE:-)
просто выбросить лишние вещи.Здесь представлена почти полная и многословная форма для всех случаев жизни. И вы можете использовать любую краткую форму.
Я называю это " ЕСЛИ НЕ СУЩЕСТВУЕТ " на стероидах. Так что это помогает мне, и я в основном это делаю.
У меня есть таблица с 14 миллионами записей. Если я хочу добавить больше данных в том же формате, есть ли способ гарантировать, что запись, которую я хочу вставить, еще не существует, без использования пары запросов (т. е. один запрос для проверки и один – для вставки)?
Гарантирует ли ограничение unique поля при выполнении insert отказ выполнения, если оно уже существует?
Ответ 1
повторные запуски конвейера не уничтожат нашу базу данных ;
повторное выполнение не прекратится из-за ошибок «дублирования первичного ключа».
Ответ 2
Решение:
INSERT INTO `table` (`value1`, `value2`)
SELECT 'stuff for value1', 'stuff for value2' FROM DUAL
WHERE NOT EXISTS (SELECT * FROM `table`
WHERE `value1`='stuff for value1' AND `value2`='stuff for value2' LIMIT 1)
Объяснение:
SELECT * FROM `table`
WHERE `value1`='stuff for value1' AND `value2`='stuff for value2' LIMIT 1
Используемое в качестве WHERE NOT EXISTS -условие определяет, существует ли уже строка с данными для вставки. После того как будет найдена одна такая строка, запрос может остановиться, поэтому LIMIT 1 (микрооптимизация может быть опущена).
Промежуточный запрос:
SELECT 'stuff for value1', 'stuff for value2' FROM DUAL
представляет значения, которые нужно вставить. DUAL относится к специальной таблице с одной строкой и одним столбцом, которая по умолчанию присутствует во всех базах данных Oracle. На MySQL-сервере версии 5.7.26 я получил действительный запрос при пропуске FROM DUAL , но более старые версии (например, 5.5.60), похоже, требуют секции FROM . При использовании WHERE NOT EXISTS промежуточного запроса возвращается пустой набор результатов, если самый внутренний запрос нашел совпадающие данные.
Внешний запрос:
INSERT INTO `table` (`value1`, `value2`)
вставляет данные, если они были возвращены промежуточным запросом.
Ответ 3
Если один из столбцов отличается, строка будет добавлена.
Если таблица пуста, строка будет добавлена.
Если существует строка, в которой все указанные столбцы имеют указанные значения, строка не будет добавлена.
Ответ 4
Попробуйте следующее:
IF (SELECT COUNT(*) FROM beta WHERE name = 'John' > 0)
UPDATE alfa SET c1=(SELECT id FROM beta WHERE name = 'John')
ELSE
BEGIN
INSERT INTO beta (name) VALUES ('John')
INSERT INTO alfa (c1) VALUES (LAST_INSERT_ID())
END
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
Читайте также: