在BEGIN ... END上下文或外部和LOOP语法中启动TRANSACTION

时间:2012-09-04 08:35:56

标签: mysql loops stored-procedures transactions

我有两个关于MySQL中的复合语句和事务的问题。

FIRST:

MySQL手册中有两个注释:

  

请注意

     

在所有存储的程序中,解析器将BEGIN [WORK]视为   BEGIN ... END块的开头。在此开始交易   上下文,改为使用START TRANSACTION。

     

请注意

     

在所有存储的程序中(存储过程和函数,触发器,   和事件),解析器将BEGIN [WORK]视为a的开头   BEGIN ... END块。使用START在此上下文中开始交易   而是交易。

我无法理解究竟是什么意思。他们的意思是我必须START TRANSACTION代替BEGINBEGIN之后?

// 1st variant:

BEGIN
   START TRANSACTION
   COMMIT
END


// 2nd variant:

START TRANSACTION
COMMIT
END

哪一种是正确的方式,第一种变体或第二种变体?

第二

我不想创建存储过程或函数。我只是想在一般流程中创建一个带有循环的Compound-Statement Block,如下所示:

USE 'someDb';
START TRANSACTION
   ... create table statement
   ... insert statement

// now I want to implement some insert/select statements using loop, I do as follows:

DELIMITER $
BEGIN
  SET @n = 1, @m = 2;
  lab1: LOOP

   ... some insert, select statements here

   END LOOP lab1;
END $
DELIMITER ;

END

COMMIT

这种结构有可能吗?因为我抛出了一个错误:

Query: BEGIN SET @n = 1, @m = 2; lab1: LOOP SELECT ...
Error Code: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SET @n = 1, @m = 2;
lab1: LOOP SELECT ...

我的问题是:

  1. 是否允许在一般流程中使用BEGIN...END而不创建和使用存储过程或函数?
  2. 是否可以在BEGIN...END内使用START TRANSACTION...COMMIT,或者我必须将START TRANSACTION...COMMIT置于BEGIN...END内?

    BEGIN
       START TRANSACTION
       COMMIT
    END
    
    // vs.
    
    START TRANSACTION
       BEGIN
       END
    COMMIT
    
  3. 如果我只想使用BEGIN...END,我是否必须使用LOOP?我可以在不启动LOOP的情况下使用BEGIN...END语法吗? LOOP手册中唯一的例子是:

      CREATE PROCEDURE doiterate(p1 INT)
         BEGIN
           label1: LOOP
             ... 
    

1 个答案:

答案 0 :(得分:13)

  1.   

    是否允许在一般流程中使用BEGIN ... END而不创建和使用存储过程或函数?

    否:复合语句只能在存储程序的主体中使用。

  2.   

    是否可以在BEGIN...END内使用START TRANSACTION...COMMIT,或者我必须将START TRANSACTION...COMMIT放在BEGIN...END内?

    START TRANSACTION;COMMIT;是单独的陈述。如果希望存储程序的主体包含多个语句,则需要将这些语句包含在某种复合语句块中,例如BEGIN ... END(类似于在括号{{1中包含语句块)在类C语言中。)

    那就是说,可能有一个只包含单个语句{ ... }START TRANSACTION;的存储程序 - 这样的程序不需要任何复合语句块,并且只是分别开始新的/提交当前的交易。

    在存储程序之外,不允许使用复合语句块,您可以将COMMIT;START TRANSACTION;语句发布为&需要时。

  3.   

    如果我只想使用COMMIT;,我是否必须使用BEGIN...END?我可以在不启动LOOP的情况下使用LOOP语法吗?

    BEGIN...END也是复合语句块,仅在存储过程中有效。将LOOP块封装在LOOP块中并不是必要,尽管这是常见的(否则很难执行任何所需的循环初始化)。

  4. 在您的情况下,您显然希望从循环结构中将数据插入表中,您将需要:

    • 定义使用BEGIN ... END;

    • 的存储程序
    • 迭代外部程序中的循环,该程序在每次迭代时执行数据库查询;或

    • 根据SQL可以直接操作的集合重新定义逻辑。