Чи є спосіб скористатися ON DUPLICATE KEY для оновлення всього, що я хотів вставити?


76

Я знаю, що ви можете використовувати ON DUPLICATE KEY UPDATEдля оновлення певного значення, якщо вже є запис для цього ключа,

Я можу зробити це:

INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1, 2, 3)
ON DUPLICATE KEY UPDATE `a`=1, `b`=2, `c`=3

Але як я можу це зробити, не виписуючи стовпці та значення двічі?


Відповіді:


103

На жаль ні.

Ви можете пройти половину шляху, не повторюючи значення:

INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);

Але ви все одно повинні перерахувати стовпці.


@Neal: Ваші значення для вставки є складними, я вважаю?
Гонки легкості на орбіті

@Neal: Зніміть цю крапку з комою. Це все один запит.
Гонки легкості на орбіті

Ха-ха дякую ^ _ ^. не помітив, що я залишив його там. Спробувати зараз.
Naftali aka Neal

3
@Sohaib UPDATE a = VALUES(a)+a, b = VALUES(b)+b, c = VALUES(c)+c:?
Гонки легкості на орбіті

2
Використання VALUES () для посилання на новий рядок і стовпці застаріло, починаючи з MySQL 8.0.20, і підлягає видаленню в майбутньому dev.mysql.com/doc/refman/8.0/en/…
BhendiGawaar

41

використання REPLACE INTO

Сенс REPLACE INTOполягає в тому, що, якщо новий запис представляє нові ключові значення, він буде вставлений як новий запис.

ЯКЩО новий запис має ключові значення, які відповідають вже існуючому запису, тоді порушення ключа буде проігноровано, а новий запис замінить попередній.


5
Ах, це може бути набагато краще. Варто зазначити, що всі поля, не вказані явно у запиті, будуть за замовчуванням, що, очевидно, відрізняється від ON DUPLICATE KEY UPDATEповедінки.
Гонки легкості на орбіті

67
Примітка. REPLACEЯкщо, якщо ключ запису збігається з чимось, що вже існує, старі рядки буде видалено та вставлено новий . Це може бути великою справою, якщо ви возитиметеся з тригерами або обмеженнями зовнішнього ключа.
cHao 02.03.12

3
Влучне зауваження. Я думаю, ви ризикуєте суттєвими ланцюговими реакціями.
Гонки легкості на орбіті

1
Також зверніть увагу, що mysqli_insert_id () не працює! "Якщо останній запит не був оператором INSERT або UPDATE, або якщо у зміненій таблиці немає стовпця з атрибутом AUTO_INCREMENT, ця функція поверне нуль."
Едвард

Детальніше про коментар cHao, це означає, що ваші нові записи матимуть інші ідентифікатори автоматичного збільшення, ніж старі "замінені" записи. Це може бути досить жахливо, якщо ви використовуєте таблицю для зв’язку десь, що не встигає замінити
Абрахам Брукс

15

Якщо це корисно, я зробив запит, щоб уникнути написання від руки останньої частини запиту "на дублікаті", для версій> = 5.0:

SELECT GROUP_CONCAT( CONCAT(COLUMN_NAME,"=values(", COLUMN_NAME,")") SEPARATOR ", ") FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'database_name' AND TABLE_NAME = 'table_name';

і його результат такий:

a=values(a), b=values(b), c=values(c), d=values(d)

у таблиці, яка має стовпці a, b, c та d, так що ви можете додати до першої частини запиту:

INSERT INTO `tableName` (`a`,`b`,`c`, `d`) VALUES (1,2,3,4) ON DUPLICATE KEY UPDATE a=values(a), b=values(b), c=values(c), d=values(d)

ОНОВЛЕННЯ: Для дуже довгого списку стовпців ви можете побачити усічений результат, ви можете використовувати цей вираз перед запитом вище (дякую дядьку iroh ):

SET SESSION group_concat_max_len = 1000000;

2
Люблю це. Іноді мені це потрібно перед вашим дуже корисним запитом. ВСТАНОВИТИ СЕСІЮ group_concat_max_len = 1000000;
Дядько Ірох,

1
Ви чудові!
Дамілола Олоуокере

1

за коментарем @ BhendiGawaar щодо @Lightness Races у відповіді Orbit, ось версія MySQL 8.019+:

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new
  ON DUPLICATE KEY UPDATE c = new.a+new.b;

АБО

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new(m,n,p)
  ON DUPLICATE KEY UPDATE c = m+n;

Працює також з set:

INSERT INTO t1 SET a=1,b=2,c=3 AS new
  ON DUPLICATE KEY UPDATE c = new.a+new.b;

INSERT INTO t1 SET a=1,b=2,c=3 AS new(m,n,p)
  ON DUPLICATE KEY UPDATE c = m+n;

Скопійовано безпосередньо з MySQL Docs

Попередження про припинення використання VALUES:

Використання VALUES () для посилання на новий рядок і стовпці застаріло, починаючи з MySQL 8.0.20, і підлягає видаленню в майбутній версії MySQL. Натомість використовуйте псевдоніми рядків і стовпців, як описано в наступних кількох параграфах цього розділу.


0

Я знаю, що це старе запитання, і це дещо нетрадиційна відповідь, але я зіткнувся з тим самим і мав проблеми із встановленням властивості group_concat_max_len, згаданого в іншій відповіді, і завжди отримував усічений результат. Іншим варіантом, з яким я врешті-решт пішов, коли писав довгий сценарій, було використання цієї формули в Excel:

=SUBSTITUTE(TRIM(A1), ",", "") & " = VALUES(" & SUBSTITUTE(TRIM(A1), ",", "") & "),"

де А1 - комірка, в яку ви копіюєте ім'я поля. Для цього швидко клацніть правою кнопкою миші таблицю та скопіюйте оператор select у буфер обміну, який дасть вам усі назви стовпців, формула видаляє коми.

Сподіваюся, це комусь допомагає!

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