Условная Вставка MySQL
У меня возникли трудности с формированием условной вставки
У меня есть x_table со столбцами (экземпляр, пользователь, элемент), где идентификатор экземпляра уникален. Я хочу вставить новую строку, только если у пользователя уже нет данного элемента.
например попытка вставить экземпляр = 919191 пользователь=123 item=456
Insert into x_table (instance, user, item) values (919191, 123, 456)
ONLY IF there are no rows where user=123 and item=456
любая помощь или руководство в правильном направлении будет высоко ценится.
12 ответов:
Если ваша СУБД не накладывает ограничений на то, из какой таблицы вы выбираете при выполнении вставки, попробуйте:
INSERT INTO x_table(instance, user, item) SELECT 919191, 123, 456 FROM dual WHERE NOT EXISTS (SELECT * FROM x_table WHERE user = 123 AND item = 456)в этой
dual- Это таблица только с одной строкой (найденная первоначально в Oracle, теперь и в другом месте). Логика заключается в том, что оператор SELECT генерирует одну строку данных с требуемыми значениями, но только тогда, когда значения еще не найдены.кроме того, посмотрите на инструкцию MERGE.
вы также можете использовать
INSERT IGNOREкоторый молча игнорирует вставку вместо обновления или вставки строки, когда у вас есть уникальный индекс (пользователь, элемент).запрос будет выглядеть так:
INSERT IGNORE INTO x_table(instance, user, item) VALUES (919191, 123, 456)вы можете добавить уникальный индекс с
CREATE UNIQUE INDEX user_item ON x_table (user, item).
вы когда-нибудь пробовали нечто подобное?
INSERT INTO x_table SELECT 919191 as instance, 123 as user, 456 as item FROM x_table WHERE (user=123 and item=456) HAVING COUNT(*) = 0;
С
UNIQUE(user, item), do:Insert into x_table (instance, user, item) values (919191, 123, 456) ON DUPLICATE KEY UPDATE user=123the
user=123бит-это "no-op", чтобы соответствовать синтаксисуON DUPLICATEпредложение, фактически ничего не делая, когда есть дубликаты.
Если вы не хотите устанавливать уникальное ограничение, это работает как шарм:
INSERT INTO `table` (`column1`, `column2`) SELECT 'value1', 'value2' FROM `table` WHERE `column1` = 'value1' AND `column2` = 'value2' HAVING COUNT(`column1`) = 0надеюсь, что это помогает !
Если вы добавляете ограничение, которое (x_table.пользователей, x_table.item) является уникальным, а затем вставка другой строки с тем же пользователем и элементом завершится ошибкой.
например:
mysql> create table x_table ( instance integer primary key auto_increment, user integer, item integer, unique (user, item)); Query OK, 0 rows affected (0.00 sec) mysql> insert into x_table (user, item) values (1,2),(3,4); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into x_table (user, item) values (1,6); Query OK, 1 row affected (0.00 sec) mysql> insert into x_table (user, item) values (1,2); ERROR 1062 (23000): Duplicate entry '1-2' for key 2
хотя это хорошо, чтобы проверить на дублирование перед вставкой данных я предлагаю вам поставить уникальное ограничение / индекс на ваших столбцах, так что никакие дубликаты данных не могут быть вставлены по ошибке.
то, что вы хотите, это
INSERT INTO table (...) SELECT ... WHERE .... от MySQL 5.6 руководство.в вашем случае это:
INSERT INTO x_table (instance, user, item) SELECT 919191, 123, 456 WHERE (SELECT COUNT(*) FROM x_table WHERE user=123 AND item=456) = 0или, может быть, так как вы не используете какую-либо сложную логику, чтобы определить, следует ли запускать
INSERTили нет, вы можете просто установитьUNIQUEнажмите на комбинацию этих двух столбцов, а затем используйтеINSERT IGNORE.
Insert into x_table (instance, user, item) values (919191, 123, 456) where ((select count(*) from x_table where user=123 and item=456) = 0);синтаксис может варьироваться в зависимости от вашей БД...
небольшая модификация ответа Алекса, вы также можете просто ссылаться на существующее значение столбца:
Insert into x_table (instance, user, item) values (919191, 123, 456) ON DUPLICATE KEY UPDATE user=user
Так что это означает PostgreSQL
INSERT INTO x_table SELECT NewRow.* FROM (SELECT 919191 as instance, 123 as user, 456 as item) AS NewRow LEFT JOIN x_table ON x_table.user = NewRow.user AND x_table.item = NewRow.item WHERE x_table.instance IS NULL
вы можете использовать следующее решение вашей проблемы:
INSERT INTO x_table(instance, user, item) SELECT 919191, 123, 456 FROM dual WHERE 123 NOT IN (SELECT user FROM x_table)
Comments