MySQL условная вставка
Мне сложно создать условный INSERT
У меня есть x_table со столбцами (экземпляр, пользователь, элемент), где уникальный идентификатор экземпляра. Я хочу вставить новую строку только в том случае, если пользователь уже не имеет данного элемента.
Например, попытка вставить экземпляр = 919191 user = 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
Любая помощь или руководство в правильном направлении будет высоко оценена.
Ответы
Ответ 1
Если ваша СУБД не накладывает ограничений на то, какую таблицу вы выбираете при выполнении вставки, попробуйте:
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, а теперь и в mysql). Логика заключается в том, что инструкция SELECT генерирует одну строку данных с необходимыми значениями, но только тогда, когда значения еще не найдены.
В качестве альтернативы посмотрите на оператор MERGE.
Ответ 2
Вы также можете использовать INSERT IGNORE
, который молча игнорирует вставку вместо обновления или вставки строки, когда у вас есть уникальный индекс (пользователь, элемент).
Запрос будет выглядеть так:
INSERT IGNORE INTO x_table(instance, user, item) VALUES (919191, 123, 456)
Вы можете добавить уникальный индекс с помощью CREATE UNIQUE INDEX user_item ON x_table (user, item)
.
Ответ 3
Вы когда-нибудь пробовали что-то подобное?
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;
Ответ 4
С помощью UNIQUE(user, item)
выполните:
Insert into x_table (instance, user, item) values (919191, 123, 456)
ON DUPLICATE KEY UPDATE user=123
бит user=123
- это "no-op", чтобы соответствовать синтаксису предложения ON DUPLICATE
, фактически не делая ничего, когда есть дубликаты.
Ответ 5
Если вы не хотите устанавливать уникальное ограничение, это работает как прелесть:
INSERT INTO `table` (`column1`, `column2`) SELECT 'value1', 'value2' FROM `table` WHERE `column1` = 'value1' AND `column2` = 'value2' HAVING COUNT(`column1`) = 0
Надеюсь, что это поможет!
Ответ 6
Если вы добавите ограничение, которое (x_table.user, 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
Ответ 7
Хотя рекомендуется проверять дублирование перед вставкой ваших данных, я предлагаю вам поместить уникальное ограничение/индекс в ваши столбцы, чтобы по ошибке не могли быть вставлены повторяющиеся данные.
Ответ 8
Вы хотите 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
.
Ответ 9
Insert into x_table (instance, user, item) values (919191, 123, 456)
where ((select count(*) from x_table where user=123 and item=456) = 0);
Синтаксис может варьироваться в зависимости от вашей базы данных...
Ответ 10
Незначительная модификация ответа Alex, вы также можете просто ссылаться на существующее значение столбца:
Insert into x_table (instance, user, item) values (919191, 123, 456)
ON DUPLICATE KEY UPDATE user=user
Ответ 11
Итак, это означает 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
Ответ 12
Вы можете использовать следующее решение для решения вашей проблемы:
INSERT INTO x_table(instance, user, item)
SELECT 919191, 123, 456
FROM dual
WHERE 123 NOT IN (SELECT user FROM x_table)