简体   繁体   English

MySQL仅在条件为真时才插入

[英]MySQL insert only if a condition is true

I have several insert statements that I only want to execute if they are true. 我有几个只在正确的情况下才想执行的插入语句。

Here is my example: 这是我的示例:

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;

Now, I only really want to run the second query if there is only 1 result for this query: 现在,如果此查询只有1个结果,我只想运行第二个查询:

SELECT job_type_id FROM job_types WHERE job_type_name = 'Cash' . SELECT job_type_id FROM job_types WHERE job_type_name = 'Cash'

If that query returns 2 results, I would want to abandon the transaction. 如果该查询返回2个结果,则我想放弃交易。

Is that possible? 那可能吗? Something I tried: 我尝试过的东西:

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

Which, obviously didn't work. 显然,这没有用。

You can use a WHERE clause for this. 您可以为此使用WHERE子句。 Convert your INSERT VALUES to an INSERT SELECT and add a WHERE clause. 将您的INSERT VALUES转换为INSERT SELECT并添加WHERE子句。

For example, 例如,

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

If Condition is true, it will insert the row. 如果Condition为true,它将插入行。 If Condition is false, the SELECT will return zero rows and thus the INSERT will insert zero rows. 如果Condition为false,则SELECT将返回零行,因此INSERT将插入零行。

If the query above does not run due to a syntax error, you can, as @spencer7593 mentioned, add FROM DUAL . 如果以上查询由于语法错误而无法运行,则可以如@ spencer7593所述,添加FROM DUAL

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

The DUAL table is essentially a dummy table that has predictable content and can be relied upon to always have at least one row . DUAL表本质上是一个虚拟表,具有可预测的内容,并且可以始终具有至少一行

Select the count into a variable and then use that in the comparison. 选择计数到一个变量中,然后在比较中使用它。

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;

To answer the question you asked, about conditionally issuing a ROLLBACK statement: 要回答您提出的有关有条件地发出ROLLBACK语句的问题:

That can not be done in the context of a single SQL statement. 在单个SQL语句的上下文中无法做到这一点。

We would need to run a separate query that returns a result, retrieve the result, and then use that result in a comparison in an if/else, and issue a separate SQL ROLLBACK statement. 我们将需要运行一个单独的查询,该查询返回一个结果,检索该结果,然后将该结果用于if / else中的比较,并发出一个单独的SQL ROLLBACK语句。

We could demonstrate how to do those steps in a MySQL stored program; 我们可以演示如何在MySQL存储程序中执行这些步骤。 but the question doesn't specifically mention using a procedure. 但是问题并没有特别提到使用过程。

Or, the same steps could be performed in a client program, issuing separate SQL statements for the SELECT query, and the ROLLBACK. 或者,可以在客户端程序中执行相同的步骤,分别为SELECT查询和ROLLBACK发布SQL语句。


I would approach the design differently. 我会以不同的方式处理设计。 If we can determine ahead of time, before we ever issue an INSERT statement, that we would want to ROLLBACK the transaction... then we could avoid performing an INSERT in the first place. 如果我们可以在发出INSERT语句之前提前确定要回滚事务……那么我们可以避免首先执行INSERT。 And avoiding the unnecessary overhead, parsing the statement, obtaining locks, writing to the log, generating rollback, wasting an AUTO_INCREMENT, etc. 并避免不必要的开销,解析语句,获得锁,写入日志,生成回滚,浪费AUTO_INCREMENT等。

In the context of a MySQL stored program (for example, a PROCEDURE), you could execute a SELECT COUNT() INTO var and then use an IF THEN ELSE block to test the value of the variable. 在MySQL存储程序(例如PROCEDURE)的上下文中,可以执行SELECT COUNT() INTO var ,然后使用IF THEN ELSE块来测试变量的值。 Or, you could setup a CONTINUE handler to handle a particular exception. 或者,您可以设置CONTINUE处理程序以处理特定的异常。

But the question doesn't specifically mention that this is in the context of a MySQL stored program. 但是问题并没有特别提到这是在MySQL存储程序的上下文中。


Personally, I would approach the design a little differently. 就个人而言,我对设计的处理方式略有不同。

I'm wondering why it's a problem that there are two or more rows with the value of 'Cash' for job_type_name . 我想知道为什么有两行或更多行具有job_type_name'Cash'值的job_type_name

I see why it would cause a problem for the INSERT statement shown in the question, the SELECT query returning more than one row is going to throw an error in the context it's in. 我知道为什么它会对问题中显示的INSERT语句造成问题,返回多行的SELECT查询将在其所处的上下文中引发错误。

But there are fixes for that. 但是,有一些修复程序。 We could take the lowest or highest value, use a MIN() or MAX() aggregate, or add an ORDER BY ... LIMIT 1 , or we could add some additional criteria that would guarantee the return of a single value. 我们可以采用最低或最高值,使用MIN()MAX()聚合,或添加ORDER BY ... LIMIT 1 ,也可以添加一些其他条件来保证返回单个值。

I'm wondering if job_type_name be UNIQUE in the job_type table. 我想知道job_type_namejob_type表中是否为UNIQUE。 Or are we only concerned that the 'Cash' value only occurs once. 还是我们只担心'Cash'值只出现一次。

Looking at the question, I can't help but wonder if this need to conditionally rollback a transaction is a symptom of a more encompassing design issue. 看着这个问题,我禁不住想知道是否需要有条件地回滚事务是更广泛的设计问题的征兆。

Looking at the question being asked, I think there is more going on here. 看着提出的问题,我认为这里还有更多事情要做。 I would take a few steps back, and reconsider the proposed design. 我将退后一步,然后重新考虑建议的设计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM