mysql系列(十四)——sql編程

一、變量的定義

mysql中的變量有兩種分別是@variable與variable;兩者的區別@variable作用範圍是整個會話,@variable稱爲系統變量使用是可以不做聲明,variable只作用一次查詢,必須聲明!

DROP PROCEDURE IF EXISTS `test_variable_produce`; // 存儲過程後面會講到
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `test_variable_produce`()
BEGIN
	DECLARE a int;
	set a = 1;
  set @b=1;
END
;;
DELIMITER ;

-----------------------

mysql> call test_variable_produce();

select a;

select @b;
Query OK, 0 rows affected

1054 - Unknown column 'a' in 'field list'
+----+
| @b |
+----+
|  2 |
+----+
1 row in set

從上面的案例可以看出,存儲過程執行之後,b是有值的,Unknown column 'a' in 'field list'

二、變量的賦值

  1. set 變量 = 值
  2. select 值 into 變量
set a =1;
set @a=1;

select 常量 into a;
select 常量 into @a;

select 字段1 into 變量 from 表 where id=id 

三、變量的調用

select 變量名

四、函數

  • 分割符說明 **: **mysql中默認的sql分隔符是“;”,在編寫函數時;表示語句的結束的符號默認也是“;”,這就導致mysql在解析sql出異常,這個時候我們就需要重新設置分隔符;修改後的分隔符在本次會話中有效。
delimiter 分隔符(介意使用 '$$'或者';;')  如 delimiter ;;
  1. 函數語法
(1)創建
delimiter 分隔符
create function 函數名(參數列表) returns 返回值類型
begin

end
分隔符
delimiter ; // 編寫結束以後將分隔符設置回默認

(2)刪除
drop function (if EXISTS ) 函數名;

(3) 查看創建函數的語句
show create function 函數名;

(4) 查看函數信息
 show function status (where name = 函數名);
 
(5) 調用
	select 函數名(參數);
  1. 簡單案例
mysql> delimiter ;;
create FUNCTION first_func (arg1 int(11)) RETURNS VARCHAR(50)
BEGIN
	return '0';
END
;;
delimiter ;

select first_func(12);
Query OK, 0 rows affected

+----------------+
| first_func(12) |
+----------------+
| 0              |
+----------------+
1 row in set

注: 函數功能,實現輸入任何一個整數,返回字符串 '0';

五、存儲過程

  1. 存儲過程語法
(1)創建
delimiter 分隔符
create PROCEDURE 名稱(模式) returns 返回值類型
begin
	sql statement;
end
分隔符
delimiter ; // 編寫結束以後將分隔符設置回默認

* 注:
  [in/out/inout] 參數名 參數類型 ..

  IN = 給參數傳入值
  OUT = 傳參, 傳入一個變量, 用於接收存儲過程內部返回的數據. 相當於Return, 不過應用在了參數
  INOUT = 調用者還可以通過 inout 參數傳遞值給存儲過程,也可以從存儲過程內部傳值給調用者

(2)刪除
drop PROCEDURE (if EXISTS ) 名稱;

(3) 查看創建函數的語句
show create PROCEDURE 名稱;

(4) 查看函數信息
 show PROCEDURE status (where name = 名稱);
 
(5) 調用
call 名稱(參數);
  1. 簡單案例
(1)無參數模式案例
mysql> delimiter ;;
mysql> create procedure test_noArgs()
    -> begin 
    ->   select 1;
    -> end
    -> ;;
Query OK, 0 rows affected
mysql> delimiter ;
mysql> call test_noArgs();
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set

Query OK, 0 rows affected
----------------------------------------------------------------
(2)IN模式案例
mysql> delimiter ;;
create procedure test_in_mode(IN flag int)
BEGIN
	if flag > 0 then 
		select "true";
	ELSE
		select "false";
	end IF;
END
;;
delimiter ;
call test_in_mode(-2);


Query OK, 0 rows affected

+-------+
| false |
+-------+
| false |
+-------+
1 row in set

Query OK, 0 rows affected
----------------------------------------------------------------
(3)OUT模式案例
mysql> delimiter ;;
mysql> create procedure test_out_mode(OUT age int)
    -> begin
    ->    set age=13;
    -> end
    -> ;;
Query OK, 0 rows affected

mysql> delimiter ;
mysql> call test_out_mode(@arg1);
Query OK, 0 rows affected

mysql> select @arg1;
+-------+
| @arg1 |
+-------+
|    13 |
+-------+
1 row in set
----------------------------------------------------------------
(4)INOUT模式案例

mysql> delimiter ;;
mysql> create procedure test_in_out_mode(INOUT age int(2))
    -> begin
    ->   select age;
    ->   set age=12;
    -> end
    -> ;;
Query OK, 0 rows affected

mysql> delimiter ;
mysql> call test_in_out_mode(@age);
+------+
| age  |
+------+
| NULL |
+------+
1 row in set

Query OK, 0 rows affected

mysql> set @arg=23;
Query OK, 0 rows affected

mysql> call test_in_out_mode(@arg);
+-----+
| age |
+-----+
|  23 |
+-----+
1 row in set

Query OK, 0 rows affected

mysql> select @arg;
+------+
| @arg |
+------+
|   12 |
+------+
1 row in set

----------------------------------------------------------------

存儲過程與函數的區別

  • 1)一般來說,存儲過程實現的功能要複雜一點,而函數的實現的功能針對性比較強。存儲過程,功能強大,可以執行包括修改表等一系列數據庫操作;用戶定義函數不能用於執行一組修改全局數據庫狀態的操作。

  • 2)對於存儲過程來說可以返回參數,如記錄集,而函數只能返回值或者表對象。函數只能返回一個變量;而存儲過程可以返回多個。存儲過程的參數可以有IN,OUT,INOUT三種類型,而函數只能有IN類~~存儲過程聲明時不需要返回類型,而函數聲明時需要描述返回類型,且函數體中必須包含一個有效的RETURN語句。

  • 3)存儲過程,可以使用非確定函數,不允許在用戶定義函數主體中內置非確定函數。

  • 4)存儲過程一般是作爲一個獨立的部分來執行( EXECUTE 語句執行),而函數可以作爲查詢語句的一個部分來調用(SELECT調用),由於函數可以返回一個表對象,因此它可以在查詢語句中位於FROM關鍵字的後面。 SQL語句中不可用存儲過程,而可以使用函數。

六、條件判斷if...elseif...else..&case...when...then

  1. if 條件 then 業務語句; end if;
mysql> DELIMITER ;;
CREATE FUNCTION `test_if_func`() RETURNS varchar(50) CHARSET utf8
BEGIN
	DECLARE flag int(8) DEFAULT 0;
	if flag > 0  then 
		return 'true';
	end IF;
	return 'false';
END
;;
DELIMITER ;

select test_if_func();
Query OK, 0 rows affected

+----------------+
| test_if_func() |
+----------------+
| false          |
+----------------+
1 row in set
  1. if 條件 then 業務語句;else 業務語句;end if;
mysql> DELIMITER ;;
CREATE FUNCTION `test_if_else_func`() RETURNS varchar(50) CHARSET utf8
BEGIN
	DECLARE flag int(8) DEFAULT 0;
	if flag > 0  then 
		return 'true';
  else
  	return 'false';
	end IF;
END
;;
DELIMITER ;

select test_if_else_func();
Query OK, 0 rows affected

+---------------------+
| test_if_else_func() |
+---------------------+
| false               |
+---------------------+
1 row in set
  1. if 條件 then 業務語句;elseif 條件 then 業務語句;else 業務語句;end if;
mysql> delimiter ;;
CREATE FUNCTION `test_if_elseif_else_func`(`age` int) RETURNS varchar(50) CHARSET utf8
BEGIN
	#Routine body goes here...	
	if age < 18 then 
		return '未成年人';
	ELSEIF age < 35 THEN
		return '青年人';
	ELSEIF age < 55 THEN
		return "老年人";
	ELSE
		return "老年人";
	end IF;
END
;;

Query OK, 0 rows affected

mysql>delimiter ;
mysql> select test_if_elseif_else_func(43);
+-------------------------+
| test_if_elseif_else(43) |
+-------------------------+
| 老年人                  |
+-------------------------+
1 row in set
  1. case 參數 when 條件值1 then sql語句;when 條件值2 then sql語句2;else sql語句3;end case;
mysql>DELIMITER ;;
CREATE FUNCTION `test_case`(`sta` tinyint) RETURNS int(11)
BEGIN
	#Routine body goes here...
	case sta
		when 1 then 
				return 1;
		when 2 then 
				return 2;
		ELSE
				return 0;
	END CASE;
END
;;
DELIMITER ;

Query OK, 0 rows affected

mysql> select test_case(13);
+---------------+
| test_case(13) |
+---------------+
|             0 |
+---------------+
1 row in set

七、循環語句

  1. while 條件 do sql語句; end while;
mysql>DELIMITER ;;
CREATE FUNCTION `test_while`() RETURNS int(11)
BEGIN
	DECLARE sum int DEFAULT 0;
	DECLARE i int DEFAULT 0;
	
	while i<=100 DO
		set sum = sum + i;
		set i = i+1;
	end WHILE;

	RETURN sum;
END
;;
DELIMITER ;

Query OK, 0 rows affected

mysql> select test_while();
+--------------+
| test_while() |
+--------------+
|         5050 |
+--------------+
1 row in set
  1. repeat sql語句; until 循環終止條件;end repeat;
mysql>DELIMITER ;;
CREATE 
FUNCTION `test_repeat`() RETURNS int(11)
BEGIN
	DECLARE sum int DEFAULT 0;
	DECLARE i int DEFAULT 0;

	REPEAT
		set sum = sum + i;
		set i = i+1;
	UNTIL i >100
	end REPEAT;
	RETURN sum;
END
;;
DELIMITER ;
Query OK, 0 rows affected

Query OK, 0 rows affected

mysql> select test_repeat();
+---------------+
| test_repeat() |
+---------------+
|          5050 |
+---------------+
1 row in set
  1. 循環標識:loop sql語句;if 跳出循環的條件 then leave 循環標識;end loop;
mysql> DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `test_loop`() RETURNS int(11)
BEGIN
	DECLARE sum int DEFAULT 0;
	DECLARE i int DEFAULT 0;

	lp1: LOOP
		set sum = sum + i;
		set i = i+1;
		if i >100 THEN
			LEAVE lp1;
		end IF;
	end LOOP;
	RETURN sum;
END
;;
DELIMITER ;

Query OK, 0 rows affected

mysql> select test_loop();
+-------------+
| test_loop() |
+-------------+
|        5050 |
+-------------+
1 row in set

八、遊標

  1. 定義(百度百科)

遊標(Cursor)是處理數據的一種方法,爲了查看或者處理結果集中的數據,遊標提供了在結果集中一次一行或者多行前進或向後瀏覽數據的能力。

  1. mysql中游標使用的步驟
  • 定義遊標:declare 遊標名稱 cursor for select c1,c2,... from tableName;
  • 遊標內容標識:declare continue handler flag for not found set flag = 0;
  • 開啓遊標:open 遊標名稱;
  • 將遊標中的值賦值給變量:fetch 遊標名稱 into arg1,arg2...;
  • 關閉遊標:close 遊標名稱;
  1. 案例
-- 將film表中的數據全量複製到tilm_tmp裏面
--
DROP TABLE IF EXISTS `film`;
CREATE TABLE `film` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uds` (`id`,`name`) USING BTREE,
  KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `film` VALUES ('1', 'film-1');
INSERT INTO `film` VALUES ('2', 'film-2');
INSERT INTO `film` VALUES ('3', 'film-3');
INSERT INTO `film` VALUES ('4', 'film-4');

DROP TABLE IF EXISTS `film_tmp`;
CREATE TABLE `film_tmp` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uds` (`id`,`name`) USING BTREE,
  KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
begin
		-- 定義變量
    declare f_id bigint(11);
    declare f_name varchar(20);
    -- 定義遊標數據是否讀取完畢的標識 
    declare flag int(1) default 0;
    -- 定義遊標
    declare film_cursor cursor for select id,name from film;
    -- 遊標內容標識值設置
    declare continue handler for not found set flag=0;
    -- 使用遊標
    open film_cursor;
    -- 處理遊標數據
    film_loop:loop
      if flag=0 then
         leave film_loop;
      end if;
      fetch film_cursor into f_id,f_name; 
			select f_id,f_name;
      insert into film_tmp value(f_id,f_name);
    end loop;
    -- 關閉遊標
    close film_cursor;
end

九、觸發器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章