Условная Вставка 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


любая помощь или руководство в правильном направлении будет высоко ценится.

552   12  

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=123

the 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

    Ничего не найдено.