PostgreSQL INSERT НА ОНОВЛЕННЯ КОНФЛІКТУ (оновлення) використовують усі виключені значення


142

Коли ви вставляєте рядок (PostgreSQL> = 9.5) і хочете, щоб можливий INSERT був таким самим, як можливий ОНОВЛЕННЯ, ви можете записати його так:

INSERT INTO tablename (id, username, password, level, email) 
                VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') 
ON CONFLICT (id) DO UPDATE SET 
  id=EXCLUDED.id, username=EXCLUDED.username,
  password=EXCLUDED.password, level=EXCLUDED.level,email=EXCLUDED.email

Чи є коротший шлях? Просто кажучи: використовуйте всі значення EXCLUDE.

У SQLite я раніше робив:

INSERT OR REPLACE INTO tablename (id, user, password, level, email) 
                        VALUES (1, 'John', 'qwerty', 5, 'john@mail.com')

43
Не справжня відповідь, але ви можете скористатися трохи короткою міткою: INSERT INTO tablename (id, username, password, level, email) VALUES (1, 'John', 'qwerty', 5, 'john@mail.com') ON CONFLICT (id) DO UPDATE SET (username, password, level, email) = (EXCLUDED.username, EXCLUDED.password, EXCLUDED.level, EXCLUDED.email).майже те саме, але легко скопіювати / вставити / керувати списком стовпців
лоша

Інший варіант - використовувати стовпці jsonb, і таким чином вам не доведеться турбуватися про стовпці
j буде

Відповіді:


162

Postgres не реалізував еквівалент INSERT OR REPLACE. З ON CONFLICTдокументів (моє наголос):

Це може бути або НЕ НІЩО, або пункт DO UPDATE із зазначенням точних деталей дії UPDATE, які слід виконати у випадку конфлікту.

Хоча це не дає вам скорочення для заміни, воно ON CONFLICT DO UPDATEзастосовується в більш загальному вигляді, оскільки дозволяє встановлювати нові значення на основі попередніх даних. Наприклад:

INSERT INTO users (id, level)
VALUES (1, 0)
ON CONFLICT (id) DO UPDATE
SET level = users.level + 1;

3
Як обережне слово, "оновлення" не є семантично тотожним "об'єднанню" стандарту SQL, хоча його зазвичай можна використовувати в тих же місцях. У мене був випадок, коли я очікував, що "оновлення конфлікту" розпочнеться, але точна проблема у вкладиші не призвела до того, що оновлення (яке б відремонтувало пошкоджену запис) не відкрилося.
pojo-guy

2
Чи можете ви розширити ", але точна проблема у вставці не спричинила оновлення"?
MrR

@ pojo-guy - Я не думаю, що ви бачили запитання від MrR - Чи можете ви розширити "але точна проблема у вставці не спричинила оновлення"?
Рандалл

Коли ви намагаєтеся вставити ... при оновленні в postgresql, результати відрізняються за певних конкретних обставин, ніж об'єднання. Випадок, на який я зіткнувся, був досить неясним і конкретним, але був повторюваним. Минуло кілька місяців, тому я не можу дати більше жодного права.
pojo-guy

Можливо, це був не конфлікт, а інша помилка, наприклад, помилка типу поля?
MrR
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.