[整理]Mysql-存儲過程 學習整理


  1. 簡單的使用 
  •     創建  

   

     DROP PROCEDURE IF EXISTS pro2; 
  
    DELIMITER // # $或 /

    CREATE PROCEDURE pro2(OUT s INT)

      BEGIN SELECT COUNT(*) INTO s FROM navi_issuer;

   END $$

點:“DELIMITER //”語句的作用是將MYSQL的結束符設置為//,因為MYSQL默認的語句結束符為分號;

為了避免與存儲過程中SQL語句結束符相沖突,需要使用DELIMITER 改變存儲過程的結束符,並以“END//”結束存儲過程。

存儲過程定義完畢之后再使用DELIMITER ;恢復默認結束符。DELIMITER 也可以指定其他符號為結束符!!!!!!!!!!!

當使用DELIMITER命令時,應該避免使用反斜杠(\)字符,因為反斜杠是MYSQL的轉義字符!!!

1) 調用

    CALL pro1(@s);
    SELECT @s;

 

 

  2.關於參數

  

DELIMITER //

DROP PROCEDURE IF EXISTS `test_param_null` //

CREATE DEFINER=`root`@`localhost` PROCEDURE `test_param_null`(IN inVal INT(4),OUT outVal INT(4))
BEGIN 
 
    DECLARE counter INT(2) DEFAULT 0;
    
    SET counter = inVal;
    
    #set outVal = 0;
    
    WHILE counter <= 100 DO
        SET outVal = outVal + counter;
        SET counter = counter +1;
    END WHILE;
END //

DELIMITER ;

 

  其中in表示輸入參數,out表示輸出參數,inout表示既可以輸入也可以輸出,存儲過程沒有返回值,所以使用 參數 獲取 程序中的值;

 

  點:

    變量使用前必須初始化--如果直接使用  CALL test_cursor(@count); 的話,得到的結果 是null,也就是說 輸入的參數 是 null的話,相加多少 都是null

即 SELECT NULL + 1 + 1 +1; 怎么都是 null

所以在這里判斷 如果 傳入的是 null,賦值為0,這樣才能有結果。

但是 為什么 

SET @count = 1 ;

        CALL test_param_null(10,@count);

    不判斷 這樣調用 結果也是null呢,不是 傳入值了嗎?

    SET @co = 1 ;

    SELECT @co + 3;

    的方式  是可以的啊

  

  • 變量定義和賦值

 

   DECLARE MYPARAM INT DEFAULT 100;
   declare v int(2) default 1;DECLARE var1,var2,var3 INT;
  SET var1=10,var2=20;
  SET var3=var1+var2;

   點:

  MYSQL中還可以通過SELECT...INTO為一個或多個變量賦值
  DECLARE NAME CHAR(50);
  DECLARE id DECIMAL(8,2); 
  SELECT id,NAME INTO id ,NAME FROM t3 WHERE id=2;  

附:http://www.cnblogs.com/doit8791/archive/2012/05/11/2495319.html 

  Mysql 常用數據類型

      1.字符數據類型

  

CHAR

1~255個字符的定長串,它的長度必須在創建時指定,否則MySQL假定為CHAR(1)

VARCHAR

可變長度,最多不超過255字節,如在創建時指定VARCHAR(n),則可存儲0~n個字符的變長串

TINYTEXT

同TEXT,最大長度為255字節

MEDUIMTEXT

同TEXT,最大長度為16K

TEXT

最大長度為64K的變長文本

LONGTEXT

同Text,最大長度為4GB(純文本,一般不會到4G)

ENUM

接受最多64K個串組成的預定義集合的某個串

SET

接受最多64K個串組成的預定義集合的零個或多個串

 

  注意: 不管任何形式的串數據類型,串值都必須在引號內(通常單引號更好);

      如果數值是計算中使用的數值,則應存儲在數值數據類型列中,如果作為字符串使用(如電話號碼、郵政編碼)則應保存在串數據類型列中。

 

    2.數值數據類型

    

類型說明

 存儲需求

 取值范圍

tinyint[(m)]

1字節

有符號值:-128 到127(- 2^7 到2^7 – 1) 

無符號值:0到255(0 到2^8 – 1)

smallint[(m)]

2字節

有符號值:-32768 到32767(- 2^15 到2^15 – 1) 

無符號值:0到65535(0 到21 6 – 1)

mediumint[(m)]

3字節

有符號值:-8388608 到8388607(- 2^23 到2^23 – 1 ) 

無符號值:0到16777215(0 到2^24 – 1)

int[(m)]

4字節

有符號值:-2147683648 到2147683647(- 2^31 到2^31- 1) 

無符號值:0到4294967295(0 到2^32 – 1)

bigint[(m)]

8字節

有符號值:-9223372036854775808 到9223373036854775807(- 2^63到2^63-1) 

無符號值:0到18446744073709551615(0到2^64 – 1)

float[(m, d)]

4字節

最小非零值:±1.175494351e – 38

double[(m, d)]

8字節

最小非零值:±2.2250738585072014e – 308

decimal (m, d)

m字節(mysql < 3.23),m+2字節(mysql > 3.23 )

可變;其值的范圍依賴於m 和d

mysql提供了5種整型: tinyint、smallint、mediumint、int和bigint(字節數1、2、3、4、8),這些類型在可表示的取值范圍上是不同的。整數列可定義為unsigned從而禁用負值;這使列的取值范圍為0以上。

 

mysql 提供三種浮點類型: float、double和decimal。與整型不同,浮點類型不能是unsigned的,其取值范圍也與整型不同,這種不同不僅在於這些類型有最大值,而且還有最小非零值。最小值提供了相應類型精度的一種度量,這對於記錄科學數據來說是非常重要的(當然,也有負的最大和最小值)。

 

在選擇了某種數值類型時,應該考慮所要表示的值的范圍,只需選擇能覆蓋要取值的范圍的最小類型即可。選擇較大類型會對空間造成浪費,使表不必要地增大,處理起來沒有選擇較小類型那樣有效。對於整型值,如果數據取值范圍較小,如人員年齡或兄弟姐妹數,則tinyint最合適。mediumint能夠表示數百萬的值並且可用於更多類型的值,但存儲代價較大。bigint在全部整型中取值范圍最大,而且需要的存儲空間是表示范圍次大的整型int類型的兩倍,因此只在確實需要時才用。對於浮點值,double占用float的兩倍空間。除非特別需要高精度或范圍極大的值,一般應使用只用一半存儲代價的float型來表示數據。

 

在定義整型列時,可以指定可選的顯示尺寸m。如果這樣,m應該是一個1 到255的整數。它表示用來顯示列中值的字符數。例如,mediumint(4)指定了一個具有4個字符顯示寬度的mediumint列。如果定義了一個沒有明確寬度的整數列,將會自動分配給它一個缺省的寬度。缺省值為每種類型的"最長"值的長度。如果某個特定值的可打印表示需要不止m個字符,則顯示完全的值;不會將值截斷以適合m個字符。需要注意的是,使用一個寬度指示器不會影響字段的大小和它可以存儲的值的范圍。

 

對每種浮點類型,可指定一個最大的顯示尺寸m 和小數位數d。m 的值應該取1 到255。d的值可為0 到3 0,但是不應大於m – 2(如果熟悉odbc 術語,就會知道m 和d 對應於odbc 概念的"精度"和"小數點位數")。m和d對float和double 都是可選的,但對於decimal是必須的。在選項m 和d時,如果省略了它們,則使用缺省值。

      3.

日期和時間數據類型MySQl中有多種表示日期和時間的數據類型。其中YEAR表示年份,DATE表示日期,TIME表示時間,DATETIME和TIMESTAMP表示日期和實踐。具體如下表:

數據類型

存儲字節數

取值范圍

DATE

4

1000-01-01——9999-12-31

TIME

3

-838:59:59——838:59:59

DATETIME

8

1000-01-01 00:00:00——9999-12-31 23:59:59

TIMESTAMP

4

19700101080001——20380119111407

YEAR

1

1901——2155

MySQL是以YYYY-MM-DD格式來顯示DATE類型的值,插入數據時,數據可以保持這種格式。另外,MySQL還支持一些不嚴格的語法格式,分隔符"-"可以用"@"、"."等符號來替代。 在插入數據時,也可以使用"YY-MM-DD"格式,YY轉化成對應的年份的規則與YEAR類型類似。如果我們想插入當前系統的時間,則可以插入CURRENT_DATE或者NOW()。

 

TIME類型表示為"時:分:秒",盡管小時范圍一般是0~23,但是為了表示某些特殊時間間隔,MySQL將TIME的小時范圍擴發了,而且支持負值。對TIME類型賦值,標准格式是'HH:MM:SS',但不一定非要是這種格式。 如果插入的是'D HH:MM:SS'格式,則類似插入了'(D*24+HH):MM:SS'。比如插入'2 23:50:50',相當於插入了'71:50:50'。如果插入的是'HH:MM'或'SS'格式,則效果是其他未被表示位的值賦為零值。比如插入'30',相當於插入了'00:00:30';如果插入'11:25',相當於插入了'11:25:00'。在MySQl中,對於'HHMMSS'格式,系統能夠自動轉化為標准格式。如果我們想插入當前系統的時間,則可以插入CURRENT_TIME或者NOW()。

 

DATETIME類型准格式為"YYYY-MM-DD HH:MM:SS",具體賦值方法與上面的方法相似。

 

TIMESTAMP的取值范圍比較小,沒有DATETIME的取值范圍大,因此輸入值時一定要保證在TIMESTAMP的范圍之內。它的插入也與插入其他日期和時間數據類型類似。那么TIMESTAMP類型如何插入當前時間?第一,可以使用CURRENT_TIMESTAMP;第二,輸入NULL,系統自動輸入當前的TIMESTAMP;第三,無任何輸入,系統自動輸入當前的TIMESTAMP。 另外有很特殊的一點:TIMESTAMP的數值是與時區相關。

 

給YEAR類型復制可以有三種方法: 第一種是直接插入4位字符串或者4位數字; 第二種是插入2位字符串,這種情況下如果插入'00'~'69',則相當於插入2000~2069;如果插入'70'~'99',則相當於插入1970~1999。第二種情況下插入的如果是'0',則與插入'00'效果相同,都是表示2000年; 第三種是插入2位數字,它與第二種(插入兩位字符串)不同之處僅在於:如果插入的是一位數字0,則表示的是0000,而不是2000年。所以在給YEAR類型賦值時,一定要分清0和'0',雖然兩者相差個引號,但實際效果確實相差了2000年。

 

數據類型

說明

TITYBLOB

最大長度為255字節

BLOB

最大長度為64KB

MEDIUMBLOB

最大長度為16MB

LONGBLOB

最大長度為4GB

 

4.二進制數據類型:二進制類型可存儲任何數據,如文字、圖像、多媒體等。具體類型描述如下:

數據類型

說明

TITYBLOB

最大長度為255字節

BLOB

最大長度為64KB

MEDIUMBLOB

最大長度為16MB

LONGBLOB

最大長度為4GB

  •  流程控制語句 WHEN...Case

  

DROP PROCEDURE IF EXISTS `test_case`;

DELIMITER //CREATE PROCEDURE test_case(IN v INT(2),OUT n INT(2))
BEGIN
    /*
    CALL test_case(3,@n);
    SELECT @n;
    */

    #declare v int(2) default 1;
    CASE v 
    WHEN 1 THEN
        SET n = v*1;
    WHEN 2 THEN
        SET n = v*4;
    WHEN 3 THEN
        SET n = v*10;
        
    SELECT n;
    
    END CASE;
END //

 

  • 流程控制語句 IF

 

DELIMITER $$
DROP PROCEDURE IF EXISTS `syntax_if`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `syntax_if`(IN id_p INT,OUT u_name VARCHAR(200))
BEGIN
    DECLARE u_p_name VARCHAR(200) DEFAULT '-NULL-';
    DECLARE num  INT(2) DEFAULT 100;
    
    
    #這是單行注釋
    /*
    問題:
    
    1.no data - zero rows fetched,selected,or processed.
    使用 SELECT fullname INTO u_p_name FROM navi_issuer   WHERE id = 1;
    的語句  總是 出 no data - zero rows fetched,selected,or processed.
    SELECT  INTO 語句沒有發揮作用。
    后來改為 
    SELECT i.fullname INTO u_p_name FROM navi_issuer i  WHERE i.id = 1;
        
    基本可以確定 的原因是  參數名稱和 要查詢的字段 名稱 的參數 重復,id 實際上是傳入的參數。
    
    這個字段名 和參數名 重復的問題一定要注意!易出錯誤且難以查找。
    
    2.sql中拼接字符 沒有 “+” 號,而是使用 CONCAT("11" ,"22","1111"....);
    
    3.SELECT就算 打印了,但是 如果寫了多行, 好像只能 打印出 第一行。
   
    4.這樣可以 動態的 調用存儲過程--動態sql? 
是否可以直接 寫 sql 時定義語句,自己測試 總是 出錯
DECLARE    @verifyUserId INT(2) ;
SET @verifyUserId = 1;
DECLARE    cashOutId INT DEFAULT 1;
DECLARE    userIp VARCHAR(200) DEFAULT '127';
================√==============
SET @verifyUserId = 1;
SET @cashOutId = 1;
SET @userIp = '1111';
INSERT INTO navi_opt_log(muser_id,opt_content,ADDTIME,addip)
VALUES(verifyUserId,CONCAT(FROM_UNIXTIME(UNIX_TIMESTAMP()),',提現申請【',cashOutId,'】已經審核通過!管理員標識',verifyUserId),
                        UNIX_TIMESTAMP(),userIp);
    */
    #SELECT id_p>0 AND id_p <num;    
    
    IF id_p>0 AND id_p > num THEN
        SELECT shortname INTO u_p_name FROM navi_issuer i  WHERE i.id = 1;
        SELECT u_p_name;
    
    ELSEIF id_p>0 AND id_p <num THEN
        SELECT i.shortname INTO u_p_name FROM navi_issuer i WHERE i.id = 2;
        #set u_p_name ='222222';
        SELECT u_p_name;
    ELSE
        SELECT i.shortname INTO u_p_name FROM navi_issuer i WHERE i.id = 3;
        SELECT u_p_name;
    END IF;#注意 enif 后面有分號。
    
    
    #IF id_p>0 AND id_p > num THEN
        #SELECT i.fullname INTO u_p_name FROM navi_issuer i WHERE i.id = 1;
    #END IF;
    
    #select count(*) into num from navi_issuer;
    
    #SELECT id_p;
    #select u_p_name;    
    
    
    SET u_name = CONCAT(u_p_name ,"TTT");
END$$

DELIMITER ;

附:

  存儲過程 操作符:

  http://de.cel.blog.163.com/blog/static/5145123620113201033629/ 

算術運算符 +SET var1=2+2; 4
-SET var2=3-2; 1
*SET var3=3*2; 6
/SET var4=10/3; 3.3333
DIV 整除 SET var5=10 DIV 3; 3
% 取模 SET var6=10%3 ; 1 比較運算符 > 大於 1>2 False
< 小於 2<1 False
<= 小於等於 2<=2 True
>= 大於等於 3>=2 True
BETWEEN 在兩值之間 5 BETWEEN 1 AND 10 True
NOT BETWEEN 不在兩值之間 5 NOT BETWEEN 1 AND 10 False
IN 在集合中 5 IN (1,2,3,4) False
NOT IN 不在集合中 5 NOT IN (1,2,3,4) True
= 等於 2=3 False
<>, != 不等於 2<>3 False
<=> 嚴格比較兩個NULL值是否相等 NULL<=>NULL True
LIKE 簡單模式匹配 "Guy Harrison" LIKE "Guy%" True
REGEXP 正則式匹配 "Guy Harrison" REGEXP "[Gg]reg" False
IS NULL 為空 0 IS NULL False
IS NOT NULL 不為空 0 IS NOT NULL True

邏輯運算符
AND  OR  XOR
位運算符 | 位或 & 位與 << 左移位 >> 右移位 ~ 位非(單目運算,按位取反)

 

 

 

 

 

  • 流程控制語句 循環---Loop...ITERATE---LEAVE loop;While....do;repeat...until
#loop test 循環測試:loop;while;repeatDROP PROCEDURE IF EXISTS `syntax_loop`;

DELIMITER //
CREATE PROCEDURE syntax_loop(INOUT loop_param INT(4),INOUT while_param INT(4),INOUT repeat_param INT(4))
    BEGIN
    
    /*
    loop1: LOOP
       SET i=i+1;
       IF i>=10 THEN         
        LEAVE loop1;
       ELSEIF MOD(i,2)=0 THEN 
        ITERATE loop1;
       END IF;
       
       SELECT CONCAT(i,' is an odd number');
    END LOOP loop1;
    
    可以這樣理解ITERATE就是我們程序中常用的contiune,而LEAVE 就是break.當然在MySQL存儲過程,需要循環結構有個名稱,其他都是一樣的.
    */
    
    # loop leave loop
    /**/
    loop1:LOOP
        SET loop_param =2*loop_param;
    
        IF(loop_param>100) THEN
            LEAVE  loop1;
        END IF;###################### Attention:end if后面有分號。。。。。。
    END LOOP loop1;
    
    
    #while do
    
    /**/
    WHILE while_param <=100 DO
        SET  while_param = 3*while_param;
    END WHILE;
    
    
    #repeat until
    REPEAT 
        SET repeat_param = 4*repeat_param;
    UNTIL        
        repeat_param >100#Attention:until 后面的的條件 后面沒有分號。    
    END REPEAT ;
    
    
    /**/
    SELECT loop_param;
    SELECT while_param;
    SELECT repeat_param;
    
    
    /* #http://www.blogjava.net/nonels/archive/2009/04/22/233324.html
    動態的調用(InOut 參數的 形式)
    SET @param_loop = 3;
    SET @param_while = 2;
    SET @param_repeat = 5;

    CALL syntax_loop(@param_loop,@param_while,@param_repeat);

    SELECT @param_loop;
    SELECT @param_while;
    SELECT @param_repeat;
    
    */END//

 

  • 游標 (光標)cursor

 

DROP PROCEDURE IF EXISTS `test_cursor`;
#DROP 這里 絕對不能用 單引號,必須 用 [`]

DELIMITER //CREATE PROCEDURE test_cursor(OUT outVal INT(10))BEGIN
    DECLARE cunter INT(2) DEFAULT 1;
    DECLARE num INT(4) DEFAULT 4;
    
    #定義游標
    DECLARE  cur CURSOR FOR SELECT id FROM  navi_issuer;
    /*
    表示將從table1表中選取col1列的內容放到游標curl中,
    即每次游標遍歷的結果都放在curl中,要注意游標只能向前遍歷,而不能向后,並且注意,游標不能更新,最后關閉游標。
    */
    
    DECLARE  CONTINUE HANDLER FOR NOT FOUND SET cunter = -1;
    #定義 當 CURSOR 沒有數據返回的 時候的 操作;
    #它的含義是:若沒有數據返回,程序繼續,並將變量 cunter 設置值 ,這種情況是出現在select XX into XXX from tablename的時候發生的。
    
        
    #打開游標
    OPEN cur;
    
    #select cur;
    
    /*
    
    變量使用前初始化的問題--如果直接使用  CALL test_cursor(@count); 的話,
    得到的結果 是null,也就是說 輸入的參數 是 null的話,相加多少 都是null

    即 SELECT NULL + 1 + 1 +1; 怎么都是 null
       */
    IF outVal IS NULL THEN
        SET outVal = 0;
    END IF;

    #select outVal;
    
    WHILE cunter >0 DO
        FETCH cur INTO num;
        
        #select num;
        
        IF num >0 THEN
         #select num;
         SET outVal = outVal + num;
        
        END IF;
        
        SELECT outVal;
    END WHILE;
    
    #關閉游標
    CLOSE cur;
    END //

 

點:

  MYSQL中,光標只能在存儲過程和函數中使用!!

DECLARE  CONTINUE HANDLER FOR NOT FOUND SET cunter = -1;
    #定義 當 CURSOR 沒有數據返回的 時候的 操作;
    #它的含義是:若沒有數據返回,程序繼續,並將變量 cunter 設置值 ,這種情況是出現在select XX into XXX from tablename的時候發生的。

  • 異常捕獲和處理

  

DECLARE  CONTINUE HANDLER FOR NOT FOUND SET cunter = -1;   
#定義 當 CURSOR 沒有數據返回的 時候的 操作;
#它的含義是:若沒有數據返回,程序繼續,並將變量 cunter 設置值 ,這種情況是出現在select XX into XXX from tablename的時候發生的。 實際上 游標的 沒有數據時 的定義 就是 捕獲操作,意為 : 當發生了 某個異常,程序 繼續,並且 賦值 給 某個變量 //方法一: 捕獲sqlstate_value DECLARE CONTINUE HANDLER FOR SQLSTATE '42000'SET @info='CAN NOT FIND'; //方法二:捕獲mysql_error_code DECLARE CONTINUE HANDLER FOR 1148 SET @info='CAN NOT FIND'; //方法三:先定義條件,然后調用 DECLARE can_not_find CONDITION FOR 1146 ; DECLARE CONTINUE HANDLER FOR can_not_find SET @info='CAN NOT FIND'; //方法四: 使用SQLWARNING DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR'; //方法五: 使用NOT FOUND DECLARE EXIT HANDLER FOR NOT FOUND SET @info='CAN NOT FIND'; //方法六: 使用SQLEXCEPTION DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR';

 

  • 數據庫交互(存儲過程中的sql語句)

uINTO用於存儲單行記錄的查詢結果 

 DECLARE total_sales NUMERIC(82);  

 SELECT SUM(sale_value) INTO total_sales FROM sales WHERE customer_id=in_customer_id;   

 

uCURSOR用於處理多行記錄的查詢結果 

  DECLARE cur1 CURSOR FOR SELECT employee_id, salary, department_id FROM employees;

  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;   

  OPEN cur1;   

 FETCH cur1 INTO l_employee_id, l_salary, l_department_id;  

  CLOSE cur1; 

 

 

uunbounded SELECT語句用於存儲過程返回結果集 ?)

 

SELECT employee_id, surname, firstname, address1, address2, zipcode, date_of_birth FROM employees 

 

 

 

u其他的SQL語句 也可以 在存儲過程中使用

UPDATEINSERTDELETECREATE TABLE非查詢語句也可以嵌入存儲過程里 

DELIMITER $$

USE `mytest`$$

DROP PROCEDURE IF EXISTS `test_sql_in_procedure`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `test_sql_in_procedure`(IN add_title VARCHAR(500),IN upt_id INT(4),IN del_id INT(4),OUT outVal VARCHAR(10))
BEGIN
/*
CALL test_sql_in_procedure('13省養老金並軌.',1,295,@outVal);
SELECT @outVal;
*/
/*
動態sql 的編譯和執行:
mysql> PREPARE prod FROM "INSERT INTO examlple VALUES(?,?)";   
mysql> SET @p='1';   
mysql> SET @q='2';   
mysql> EXECUTE prod USING @p,@q;   
mysql> SET @name='3';   
mysql> EXECUTE prod USING @p,@name;   
mysql> DEALLOCATE PREPARE prod;  
*/
    DECLARE num INT(2) DEFAULT 0;
    
    #insert
    IF add_title IS NULL OR add_title ='' THEN
        SET add_title = '空值。。。';
    END IF;
    
    INSERT INTO navi_new (title) VALUES(add_title);
    #update
    IF upt_id IS NULL OR upt_id < 1 THEN
        SET upt_id = 1;
    END IF;
    
    UPDATE navi_issuer  SET shortname = CONCAT(shortname,'_UPT_',NOW()) WHERE id = upt_id;
    
    #delete
    
    IF del_id IS NULL OR del_id <1 THEN
        SET del_id = 295;
    END IF;
    
    DELETE FROM navi_issuer WHERE id = del_id;
    
    
    SET num = 3;
    
    SET outVal = num;
END$$

DELIMITER ;

 

u動態sql 的執行和引用

(怎么獲取 update 語句的 影響了多少行 的那個 返回值?)
http://maoyifa100.iteye.com/blog/1900305  
語法[sql]PREPARE statement_name FROM sql_text /*定義*/   
EXECUTE statement_name [USING variable [,variable...]] /*執行預處理語句*/  
DEALLOCATE PREPARE statement_name /*刪除定義*/[sql] mysql> PREPARE prod FROM "INSERT INTO examlple VALUES(?,?)"; mysql> SET @p='1'; mysql> SET @q='2'; mysql> EXECUTE prod USING @p,@q; mysql> SET @name='3'; mysql> EXECUTE prod USING @p,@name; mysql> DEALLOCATE PREPARE prod;

1.用變量做表名: 簡單的用set或者declare語句定義變量,然后直接作為sql的表名是不行的,mysql會把變量名當作表名。

在其他的sql數據庫中也是如 此,mssql的解決方法是將整條sql語句作為變量,其中穿插變量作為表名,然后用sp_executesql調用該語句。 

這在mysql5.0之前是不行的,5.0之后引入了一個全新的語句,可以達到類似sp_executesql的功能(僅對procedure有 效,function不支持動態查詢): 

PREPARE stmt_name FROM preparable_stmt;

 EXECUTE stmt_name [USING @var_name [, @var_name] ...]; 

{DEALLOCATE | DROPPREPARE stmt_name; 

 

  • 常用函數

  

CONCAT:SELECT CONCAT('FIRST ', 'SECOND',’1111’,......);
SET title=REPLACE(sendTitle,'webName',webName);
Now();
。。。。。

mysql常用函數 - sugang_ximi的專欄 - 博客頻道 - CSDN.NET http://blog.csdn.net/sugang_ximi/article/details/6664748
MySql 存儲過程中要用到的運算符 - de.cel的日志 - 網易博客 http://de.cel.blog.163.com/blog/static/5145123620113201033629/

mysql存儲過程基本函數

一.字符串類

CHARSET(str) //返回字串字符集
CONCAT (string2 [,... ]) //連接字串
INSTR (STRING ,SUBSTRING ) //返回substring首次在string中出現的位置,不存在返回0
LCASE (string2 ) //轉換成小寫
LEFT (string2 ,LENGTH ) //從string2中的左邊起取length個字符
LENGTH (STRING ) //string長度
LOAD_FILE (file_name ) //從文件讀取內容
LOCATE (SUBSTRING , STRING [,start_position ] ) 同INSTR,但可指定開始位置
LPAD (string2 ,LENGTH ,pad ) //重復用pad加在string開頭,直到字串長度為length
LTRIM (string2 ) //去除前端空格
REPEAT (string2 ,COUNT ) //重復count次
REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替換search_str
RPAD (string2 ,LENGTH ,pad) //在str后用pad補充,直到長度為length
RTRIM (string2 ) //去除后端空格
STRCMP (string1 ,string2 ) //逐字符比較兩字串大小,
SUBSTRING (str , POSITION [,LENGTH ]) //從str的position開始,取length個字符,
注:mysql中處理字符串時,默認第一個字符下標為1,即參數position必須大於等於1
mysql> SELECT SUBSTRING(’abcd’,0,2);
+———————–+
| SUBSTRING(’abcd’,0,2) |
+———————–+
| |
+———————–+
1 ROW IN SET (0.00 sec)
mysql> SELECT SUBSTRING(’abcd’,1,2);
+———————–+
| SUBSTRING(’abcd’,1,2) |
+———————–+
| ab |
+———————–+
1 ROW IN SET (0.02 sec)
TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符
UCASE (string2 ) //轉換成大寫
RIGHT(string2,LENGTH) //取string2最后length個字符
SPACE(COUNT) //生成count個空格

二.數學類

ABS (number2 ) //絕對值
BIN (decimal_number ) //十進制轉二進制
CEILING (number2 ) //向上取整
CONV(number2,from_base,to_base) //進制轉換
FLOOR (number2 ) //向下取整
FORMAT (number,decimal_places ) //保留小數位數
HEX (DecimalNumber ) //轉十六進制
注:HEX()中可傳入字符串,則返回其ASC-11碼,如HEX(’DEF’)返回4142143
也可以傳入十進制整數,返回其十六進制編碼,如HEX(25)返回19
LEAST (number , number2 [,..]) //求最小值
MOD (numerator ,denominator ) //求余
POWER (number ,POWER ) //求指數
RAND([seed]) //隨機數
ROUND (number [,decimals ]) //四舍五入,decimals為小數位數]
注:返回類型並非均為整數,如:
(1)默認變為整形值
mysql> SELECT ROUND(1.23);
+————-+
| ROUND(1.23) |
+————-+
| 1 |
+————-+
1 ROW IN SET (0.00 sec)
mysql> SELECT ROUND(1.56);
+————-+
| ROUND(1.56) |
+————-+
| 2 |
+————-+
1 ROW IN SET (0.00 sec)

(2)可以設定小數位數,返回浮點型數據
mysql> SELECT ROUND(1.567,2);
+—————-+
| ROUND(1.567,2) |
+—————-+
| 1.57 |
+—————-+
1 ROW IN SET (0.00 sec)

SIGN (number2 ) //返回符號,正負或0
SQRT(number2) //開平方


三.日期時間類
ADDTIME (date2 ,time_interval ) //將time_interval加到date2
CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //轉換時區
CURRENT_DATE ( ) //當前日期
CURRENT_TIME ( ) //當前時間
CURRENT_TIMESTAMP ( ) //當前時間戳
DATE (DATETIME ) //返回datetime的日期部分
DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或時間
DATE_FORMAT (DATETIME ,FormatCodes ) //使用formatcodes格式顯示datetime
DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上減去一個時間
DATEDIFF (date1 ,date2 ) //兩個日期差
DAY (DATE ) //返回日期的天
DAYNAME (DATE ) //英文星期
DAYOFWEEK (DATE ) //星期(1-7) ,1為星期天
DAYOFYEAR (DATE ) //一年中的第幾天
EXTRACT (interval_name FROM DATE ) //從date中提取日期的指定部分
MAKEDATE (YEAR ,DAY ) //給出年及年中的第幾天,生成日期串
MAKETIME (HOUR ,MINUTE ,SECOND ) //生成時間串
MONTHNAME (DATE ) //英文月份名
NOW ( ) //當前時間
SEC_TO_TIME (seconds ) //秒數轉成時間
STR_TO_DATE (STRING ,FORMAT ) //字串轉成時間,以format格式顯示
TIMEDIFF (datetime1 ,datetime2 ) //兩個時間差
TIME_TO_SEC (TIME ) //時間轉秒數]
WEEK (date_time [,start_of_week ]) //第幾周
YEAR (DATETIME ) //年份
DAYOFMONTH(DATETIME) //月的第幾天
HOUR(DATETIME) //小時
LAST_DAY(DATE) //date的月的最后日期
MICROSECOND(DATETIME) //微秒
MONTH(DATETIME) //月
MINUTE(DATETIME) //分
附:可用在INTERVAL中的類型
DAY ,DAY_HOUR ,DAY_MINUTE ,DAY_SECOND ,HOUR ,HOUR_MINUTE ,HOUR_SECOND ,MINUTE ,MINUTE_SECOND,MONTH ,SECOND ,YEAR
 
         

 



 

  •   TIPS

  ◆存儲過程里面是可以調用其他存儲過程的,使用CALL語句調用其他存儲過程就可以了

  存儲過程參數列表里的參數名盡量不要和數據庫中表的字段名一樣,否則有可能出錯

  存儲過程的參數可以使用中文,在定義存儲過程的時候加上character set gbk就可以了

  例如

    CREATE PROCEDURE useInfo(IN u_name VARCHAR(50) CHARACTER SET gbk,OUT u_age INT)

 

 

  • 其他命令
SHOW  FUNCTION STATUS LIKE '%name_from_t3%'like 存儲過程名稱
SHOW CREATE FUNCTION  name_from_t3;查看定義

SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME=' sp_name ' ; 
從information_schema.Routines表中查看存儲過程和函數的信息

DROP FUNCTION IF EXISTS `name_from_t3`$$

 

  •  試例

  1.

CREATE PROCEDURE putting_it_all_together(in_department_id INT)   
    MODIFIES SQL DATA   BEGIN   
    DECLARE l_employee_id INT;   
    DECLARE l_salary NUMERIC(8,2);   
    DECLARE l_department_id INT;   
    DECLARE l_new_salary NUMERIC(8,2);   
    DECLARE done INT DEFAULT 0;   
  
    DECLARE cur1 CURSOR FOR   
        SELECT employee_id, salary, department_id   
        FROM employees   
        WHERE department_id=in_department_id;   
  
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;   
  
    CREATE TEMPORARY TABLE IF NOT EXISTS emp_raises   
        (employee_id INT, department_id INT, new_salary NUMERIC(8,2));   
  
    OPEN cur1;   
    emp_loop: LOOP   
        FETCH cur1 INTO l_employee_id, l_salary, l_department_id;   
        IF done=1 THEN    /* No more rows */  
            LEAVE emp_loop;   
        END IF;   
        CALL new_salary(1_employee_id, l_new_salary); /* Get new salary */  
        IF (l_new_salary <> l_salary) THEN  /* Salary changed */  
            UPDATE employees   
                SET salary=l_new_salary   
            WHERE employee_id=l_employee_id;   
            /* Keep track of changed salaries */  
            INSERT INTO emp_raises(employee_id, department_id, new_salary)   
                VALUES (l_employee_id, l_department_id, l_new_salary);   
        END IF:   
    END LOOP emp_loop;   
    CLOSE cur1;   
    /* Print out the changed salaries */  
    SELECT employee_id, department_id, new_salary from emp_raises   
        ORDER BY employee_id;   END;  

 

 

文章列表:

Mysql存儲過程-博客園找找看  http://zzk.cnblogs.com/s?w=Mysql%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B&t=b

我的MYSQL學習心得(十) 自定義存儲過程和函數 - 樺仔 - 博客園  http://www.cnblogs.com/lyhabc/p/3793524.html



MySQL數據庫新特性之存儲過程入門教程_知識庫_博客園  http://kb.cnblogs.com/page/107457/



MySQL 存儲過程 常用語法 - juanna_ding的專欄 - 博客頻道 - CSDN.NET  http://blog.csdn.net/juanna_ding/article/details/5381188

MySQL存儲過程詳解  mysql 存儲過程_王者佳暮_新浪博客  http://blog.sina.com.cn/s/blog_52d20fbf0100ofd5.html





mysq 存儲過程判斷為空null , mysql存儲過程 字符串拼接 - 不念書的小子 - ITeye技術網站  http://tompig.iteye.com/blog/1568213

MySql 存儲過程中要用到的運算符 - de.cel的日志 - 網易博客  http://de.cel.blog.163.com/blog/static/5145123620113201033629/

Mysql學習筆記之常用數據類型 - yingsuixindong - 博客園  http://www.cnblogs.com/doit8791/archive/2012/05/11/2495319.html



存儲過程和函數的區別 - lengbingshy - 博客園  http://www.cnblogs.com/lengbingshy/archive/2010/02/25/1673476.html

  

2015-10-28 16:18:18

DELIMITER $$

CREATE PROCEDURE pro2(OUT s INT)

BEGIN SELECT COUNT(*INTO s FROM navi_issuer;

END $$


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM