2016-09-28 3 views
1

У меня есть несколько операторов вставки, которые я хочу выполнить только в том случае, если они истинны.MySQL вставить только в том случае, если условие истинно

Вот мой пример:

START TRANSACTION; 

INSERT INTO fields (field_name, control_type_id, needs_approval) 
VALUES 
('Array Photos', 3, 0); 

INSERT INTO field_to_job_type (field_id, job_type_id, sequence_number, parent_id) 
VALUES 
(last_insert_id(), (SELECT job_type_id FROM job_types WHERE job_type_name = 'Cash'), 1, (SELECT field_id FROM fields where field_name = 'Photo Pack')); 

COMMIT; 

Теперь я только действительно хочу, чтобы запустить второй запрос, если есть только один результат для этого запроса:

SELECT job_type_id FROM job_types WHERE job_type_name = 'Cash'.

Если этот запрос возвращает 2 результата, я хотел бы отказаться от транзакции.

Возможно ли это? Что-то я пробовал:

START TRANSACTION; 
INSERT ...; 
INSERT ...; 
IF(SELECT count(job_type_name) FROM job_types WHERE job_type_name = 'Cash') = 1, 'COMMIT', 'ROLLBACK'); 

Который, очевидно, не работал.

+1

Отказавшись от сделки, вы имеете в виду откат первой вставки? – RiggsFolly

+0

@FlorianHeer Я не вижу, что как цель обмана – Drew

+0

выберите счетчик (*) в var и сделайте блок 'if' – Drew

ответ

1

Выберите счетчик в переменной, а затем используйте это для сравнения.

DECLARE total_row INT DEFAULT 0 

START TRANSACTION; 

INSERT INTO fields (field_name, control_type_id, needs_approval) 
VALUES ('Array Photos', 3, 0); 


SELECT count(job_type_name) FROM job_types WHERE job_type_name = 'Cash' INTO total_rows; 

IF total_rows =2 THEN 
    ROLLBACK; 
ELSE 

    INSERT INTO field_to_job_type (field_id, job_type_id, sequence_number, parent_id) 
    VALUES (last_insert_id(), (SELECT job_type_id FROM job_types WHERE job_type_name = 'Cash'), 1, (SELECT field_id FROM fields where field_name = 'Photo Pack')); 
    COMMIT; 
END IF; 
2

Для этого можно использовать оговорку WHERE. Преобразуйте значения INSERT VALUES в INSERT SELECT и добавьте пункт WHERE.

Например,

INSERT INTO fields (field_name, control_type_id, needs_approval) 
SELECT 
'Array Photos', 3, 0 
WHERE Condition; 

Если условие истинно, то он будет вставить строку. Если Condition is false, SELECT вернет нулевые строки и, таким образом, INSERT вставляет нулевые строки.

Если указанный выше запрос не выполняется из-за синтаксической ошибки, вы можете, как указано в @ spencer7593, добавить FROM DUAL.

INSERT INTO fields (field_name, control_type_id, needs_approval) 
SELECT 
'Array Photos', 3, 0 
FROM DUAL 
WHERE Condition; 

В таблице DUAL является по существу dummy table that has predictable content and can be relied upon to always have at least one row.

+0

Я думаю, что в SELECT должно быть предложение FROM, прежде чем мы сможем добавить предложение WHERE. Для этого мы могли бы использовать специальную таблицу DUAL, например. 'SELECT 'Array Photos', 3, 0 FROM DUAL WHERE ...' – spencer7593

+0

@ spencer7593 Вы попробовали? Это дало вам синтаксическую ошибку? –

+1

** 'Код ошибки 1604: ... правильный синтаксис для использования рядом с 'WHERE 1 = 1'' ** – spencer7593

1

Чтобы ответить на поставленный вопрос вы, о выдаче условно ROLLBACK заявление:

Это не может быть сделано в контексте одного оператора SQL.

Нам нужно запустить отдельный запрос, который возвращает результат, извлекает результат и затем использует этот результат для сравнения в if/else и выдает отдельный оператор SQL ROLLBACK.

Мы могли бы продемонстрировать, как это сделать в хранимой программе MySQL; но в вопросе конкретно не упоминается использование процедуры.

Или же такие же шаги могут быть выполнены в клиентской программе, выпуская отдельные инструкции SQL для запроса SELECT и ROLLBACK.


Я подойду к дизайну по-разному. Если мы сможем заранее определить, прежде чем мы когда-нибудь опубликуем заявление INSERT, мы хотели бы выполнить ROLLBACK транзакцию ... тогда мы могли бы избежать выполнения INSERT в первую очередь. И избегая ненужных накладных расходов, анализируя заявление, получая блокировки, записывая в журнал, генерируя откат, теряя AUTO_INCREMENT и т. Д.

В контексте хранимой программы MySQL (например, ПРОЦЕДУРА) вы можете выполнить команду SELECT COUNT() INTO var, а затем использовать блок IF THEN ELSE для проверки значения переменной. Или вы можете настроить обработчик CONTINUE для обработки конкретного исключения.

Но в этом вопросе особо не упоминается, что это в контексте хранимой в MySQL программы.


Лично я подошел бы к дизайну немного по-другому.

Мне интересно, почему это проблема, что есть две или более строк со значением 'Cash' для job_type_name.

Я понимаю, почему это вызвало бы проблемы для инструкции INSERT, показанной в этом вопросе, то ВЫБРАТЬ запрос возвращение более чем один ряд будет выдавать ошибку в контексте находится.

Но есть исправления для что. Мы можем взять самое низкое или самое высокое значение, использовать агрегат MIN() или MAX() или добавить ORDER BY ... LIMIT 1, или мы могли бы добавить дополнительные критерии, которые гарантировали бы возврат одного значения.

Мне интересно, если job_type_name быть УНИКАЛЬНЫМ в таблице job_type. Или нас беспокоит только то, что значение 'Cash' происходит только один раз.

Рассматривая вопрос, я не могу не задаться вопросом, нужно ли это условно откатывать транзакцию, являясь симптомом более сложной проблемы дизайна.

Если вы хотите задать вопрос, я думаю, что здесь происходит больше. Я бы сделал несколько шагов назад и пересмотрел предлагаемый дизайн.

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