2012-09-04 84 views
5

我有兩個關於MySQL中複合語句和事務的問題。BEGIN ... END內部或外部的START TRANSACTION和LOOP語法

FIRST:

有兩個音符的MySQL手冊:

內的所有存儲的程序,解析器對待BEGIN [WORK]作爲 開始的BEGIN .. END塊。要在此 上下文中開始交易,請改用START TRANSACTION。

內的所有存儲程序(存儲過程和函數,觸發器, 和事件),解析器對待BEGIN [WORK]作爲 BEGIN ... END塊的開始。在這種情況下開始一個事務,改爲START TRANSACTION。

我不明白究竟是什麼意思。他們的意思是我必須把START TRANSACTION而不是BEGINBEGIN之後?

// 1st variant: 

BEGIN 
    START TRANSACTION 
    COMMIT 
END 


// 2nd variant: 

START TRANSACTION 
COMMIT 
END 

哪一個是正確的方法,第一個變體或第二個變體?

SECOND:

我不想創建存儲過程或函數。我只是想在一般的流程來創建其內部循環複合 - 語句塊,就像這樣:

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. 是否允許在START TRANSACTION...COMMIT裏面使用BEGIN...END或者我要把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 
         ... 
    

回答

10
  1. 是否允許使用BEGIN ... END只是一般流程,而無需創建和使用存儲過程或函數?

    否:複合語句只能在存儲程序的主體中使用。

  2. 是否允許使用BEGIN...ENDSTART TRANSACTION...COMMIT內或我必須把START TRANSACTION...COMMITBEGIN...END裏面?

    START TRANSACTION;COMMIT;是單獨的語句。如果您希望存儲程序的主體包含多個語句,則需要將這些語句包含在某種複合語句塊中,例如BEGIN ... END(這類似於在類似C語言中使用大括號{ ... }來包含語句塊)。

    這就是說,你可以存儲程序僅包含單語句START TRANSACTION;COMMIT; —這樣的程序將不需要任何複合語句塊只會開始一個新的/分別提交當前事務。

    在存儲的程序之外,不允許複合語句塊,在需要時可以發出START TRANSACTION;COMMIT;語句作爲&。

  3. 我所說的一切手段都使用BEGIN...END如果我只想LOOP使用?我可以只使用LOOP語法,而不用啓動BEGIN...END

    LOOP也是一個複合語句塊,它只在存儲過程中有效。它不是所必需的BEGIN ... END塊中包含塊,雖然它是通常的(否則很難執行任何所需的循環初始化)。

在你的情況,你顯然希望將數據插入到從循環結構的表,你要麼需要:

  • 定義您使用LOOP存儲的程序;

  • 在每次迭代執行數據庫查詢的外部程序中迭代循環;或

  • 根據SQL可以直接操作的集重新定義您的邏輯。

+0

爲什麼循環只能存在於存儲過程中?似乎遲遲不得不創建一個臨時存儲過程只是做一個簡單的循環插入..... – Pacerier

+0

@Prier:因爲這是業務邏輯屬於你的應用程序代碼,而不是數據庫層。 – eggyal

+0

@eggyal雖然我完全同意你的看法,但是Pacerier有一個非常有效的觀點,爲什麼mysql在存儲程序和標準查詢方面表現不同 –