2013-10-03 5 views
0

INSERT IGNORE не работает, потому что на самом деле не будет ключевого конфликта.INSERT, если родственная строка не существует

Это для очереди выполнения. Для одного приложения мне не нужны две строки со статусом S (для «запущено»). Однако другие приложения должны иметь возможность - в частности, если я хочу заставить сразу два рабочих элемента, я могу. Вот почему это не ограничение базы данных.

Так что немного сложно сказать в SQL "insert where where does not exist." Это работает:

insert into user_queue_google 
(user_id, status, start_timestamp) 
(select 221, 'S', NOW() FROM filter_type 
WHERE 221 not in (select user_id from user_queue_google where status = 'S') limit 1); 

Проблема заключается в том filter_type совершенно не связаны таблицы, что я просто знаю мало и бывает, никогда не будет пустым. Если по какой-то причине он был пуст, это потерпит неудачу.

Могу ли я избежать этого ужасного взлома без использования хранимых программ или логики IF/THEN в моей программе SQL?

+0

возможно дубликат [MySQL Условный Insert] (http://stackoverflow.com/questions/913841/mysql-conditional-insert) – pilcrow

ответ

0

Используйте dual системной фиктивной таблице

insert into user_queue_google (user_id, status, start_timestamp) 
select 221, 'S', NOW() 
from dual 
WHERE not exists 
(
    select user_id 
    from user_queue_google 
    where status = 'S' 
    and user_id = 221 
) 

Вам разрешаются указать DUAL в качестве фиктивного имени таблицы в ситуациях, когда не ссылаются никаких таблиц

Source

+0

Как насчет этого бита в документе - «MySQL может игнорировать предложения». Насколько это плохо? – djechlin

0

Вам нужны иметь индекс UNIQUE для INSERT IGNORE для эффективной работы. Что вы можете сделать, это добавить дополнительный столбец, который по умолчанию что-то безобидное, но может быть изменен на уникальный ключ:

CREATE UNIQUE INDEX index_block ON user_queue_google (user_id, force); 

Установите force как столбец, который имеет DEFAULT 0. Если вы хотите, чтобы заставить два рабочих места для запуска в то же время, установить его на что-то другое, чтобы избежать конфликта:

UPDATE user_queue_google SET status='S', force=UNIX_TIMESTAMP() WHERE user_id=221 

Это будет высвободить новый слот для вставки новых рабочих мест.

0

Это должно работать:

insert into user_queue_google 
(user_id, status, start_timestamp) 
select 
    A.user_id, 
    A.status, 
    A.start_timestamp 
FROM 
    (SELECT 
    221 user_id, 
    'S' status, 
    NOW() start_timestamp) AS A 
    LEFT JOIN user_queue_google ON A.user_id = user_queue_google.user_id AND A.status = user_queue_google.status 
WHERE 
    user_queue_google.user_id IS NULL; 

Смотрите приложенный скрипку Insert if row doesn't exist

Смежные вопросы