仅当条件为真时才插入MySQL

时间:2016-09-28 22:06:24

标签: mysql transactions

我有几个插入语句,如果它们是真的我只想执行。

以下是我的例子:

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;

现在,如果此查询只有1个结果,我真的只想运行第二个查询:

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');

其中,显然没有用。

3 个答案:

答案 0 :(得分:4)

您可以使用WHERE子句。将INSERT VALUES转换为INSERT SELECT并添加WHERE子句。

例如,

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

如果Condition为true,则会插入该行。如果Condition为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

答案 1 :(得分:2)

在变量中选择计数,然后在比较中使用它。

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 :(得分:1)

回答你提出的问题,关于有条件地发出ROLLBACK声明:

在单个SQL语句的上下文中无法完成。

我们需要运行一个单独的查询来返回结果,检索结果,然后在if / else中使用该结果进行比较,并发出单独的SQL ROLLBACK语句。

我们可以演示如何在MySQL存储程序中执行这些步骤;但问题没有特别提及使用程序。

或者,可以在客户端程序中执行相同的步骤,为SELECT查询和ROLLBACK发出单独的SQL语句。

我会以不同的方式接近设计。如果我们可以提前确定,在我们发出INSERT语句之前,我们想要ROLLBACK事务......那么我们可以避免首先执行INSERT。并避免不必要的开销,解析语句,获取锁,写入日志,生成回滚,浪费AUTO_INCREMENT等。

在MySQL存储程序(例如,PROCEDURE)的上下文中,您可以执行SELECT COUNT() INTO var,然后使用IF THEN ELSE块来测试变量的值。或者,您可以设置CONTINUE处理程序来处理特定异常。

但问题并没有特别提到这是在MySQL存储程序的上下文中。

就个人而言,我会以不同的方式接近设计。

我想知道为什么'Cash'有两行或多行job_type_name的问题。

我明白为什么它会导致问题中显示的INSERT语句出现问题,返回多行的SELECT查询将在它所处的上下文中抛出错误。

但是有一些修复方法。我们可以采用最低或最高值,使用MIN()MAX()聚合,或添加ORDER BY ... LIMIT 1,或者我们可以添加一些额外的标准来保证返回单个值。

我想知道job_type_name表中job_type是否独一无二。或者我们只担心'Cash'值只出现一次。

看看这个问题,我不禁想知道是否需要有条件地回滚交易是一个更具包容性的设计问题的症状。

看看被问到的问题,我认为这里还有更多问题。我会稍微退一步,重新考虑提议的设计。