背景:sql
要求從數據庫
balance_0x123145d67520b4h63B9D60d7C1435bffF41aFa25 這個表沒有goods_id
導出數據到函數
balance_25 這個表多了一個 goods_id 字段,同時還要把這個goods_id 存進去(就是上面的表名後綴,也就是goods表的id)
將表名後綴取後兩位,把全部後綴相同的表數據合併到一張表,並且不能肯定這種表有多少個,只能選擇寫個過程來處理了,資源
這種表名後綴是由goods表的id產生的,有多少個id就有多少這種表,因此下面這條sql查出來是一個集合string
SELECT `id` FROM goods WHERE `name` IS NOT NULL;
正文:變量
既然說到過程和函數,就要看一下它們的區別以及我爲何要選擇過程來處理而不是函數;date
1. 存儲函數有且只有一個返回值,而存儲過程不能有返回值。 2. 函數只能有輸入參數,並且不能帶in, 而存儲過程能夠有多個in,out,inout參數。 3. 存儲過程當中的語句功能更強大,存儲過程能夠實現很複雜的業務邏輯,而函數有不少限制,如不能在函數中使用insert,update,delete,create等語句;存儲函數只完成查詢的工做,可接受輸入參數並返回一個結果,也就是函數實現的功能針對性比較強。 4. 存儲過程能夠調用存儲函數。但函數不能調用存儲過程。 5. 存儲過程通常是做爲一個獨立的部分來執行(call調用)。而函數能夠做爲查詢語句的一個部分來調用.
那麼到了個人需求:select
1. 我不須要返回值; 2. 不須要傳遞參數; 3. 我須要執行insert、select等sql
這樣只能選擇寫一個過程(雖然很麻煩,but I like)循環
#以root用戶建立一個名稱爲`PROCEDURE_BALANCE`的存儲過程 CREATE DEFINER=`root`@`%` PROCEDURE `PROCEDURE_BALANCE`() BEGIN #定義判斷變量 DECLARE flag varchar(50); #定義名爲goods_id的遊標(查詢goods表name不爲空的全部id,賦值給goods_id) DECLARE goods_id CURSOR FOR SELECT `id` FROM goods WHERE `name` IS NOT NULL; #循環賦初始值 DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag=NULL; #打開遊標 OPEN goods_id; #遊標讀取下一行 FETCH goods_id INTO flag; #定義循環 WHILE (flag is not null ) DO #sql拼接,替換相關變量 PS: 拼接表名這種能夠用'',可是拼接WHERE條件這種,好比 id='11',就須要三個''這種單引號,這裏細心想一下就能夠理解 SET @string_sql = CONCAT('INSERT INTO userbalance_',RIGHT (flag, 2),'(SELECT id,''',flag,''',userAddress,amount,freezeAccount,createdAt,updatedAt,deletedAt FROM userbalance_',flag,')'); #這個是打印每條sql,能夠不要 SELECT @string_sql; #建立預處理語句 PREPARE st FROM @string_sql; #執行這個sql EXECUTE st; #釋放預處理語句,(若是不釋放,在存儲過程結束以後,該預處理語句仍然會有效,佔用數據庫資源) DEALLOCATE PREPARE st; #賦值下一個遊標 FETCH goods_id INTO flag; END WHILE; #關閉遊標, PS:用完後必須關閉,並且必須在循環外關閉 CLOSE goods_id; END #PS:遊標必須在定義處理程序以前被定義,但變量必須在定義遊標以前被定義,順序就是變量定義-遊標定義-處理程序.