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

九、触发器

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