Oracle sql вставить если не существует

Обновлено: 06.07.2024

Я хочу сделать вставку 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

  1. повторные запуски конвейера не уничтожат нашу базу данных ;

  2. повторное выполнение не прекратится из-за ошибок «дублирования первичного ключа».

Ответ 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

Мы будем очень благодарны

если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

Читайте также: