数据库编程
数据库编程
过程化SQL
单行注释,使用“##” 或 “–”;多行注释,C语言风格的注释:
/* **/*
SQL语句的结束标记,默认为:分号 ;
可使用DELIMITER <符号>修改SQL语句的结束标记
<符号>可以是:$$、或%%等。
例如:DELIMITER $$
避免使用反斜杠“/”字符,因为它是MySQL的转义字符。
程序块
BEGIN
SQL语句 | SQL语句块
END
BEGIN…END语句块包含了该程序块的所有处理操作,允许语句块嵌套。
在MySQL中单独使用BEGIN…END语句块没有任何意义,只有将其封装在函数、存储过程、触发器等存储程序内部才有意义
常量
| 类型 | |
|---|---|
| 字符串常量 | 单引号或双引号括起来的字符序列 |
| 数值常量 | 整数常量,例如:10;小数常量,例如:12.8 |
| 日期和时间常量 | 用特定格式的字符日期值表示,用单引号括起来例如:’2020-10-29’ |
| 布尔常量 | true和false,SQL命令运行结果用1代表true,用0代表false |
| NULL值 | 适用于各种字段类型,通常表示“不确定的值”;NULL值参与的运算,结果仍为NULL值 |
变量
系统变量
系统定义,MySQL服务器层面,用户不能定义只能使用
可进一步分为以下两类:
全局变量global variable
会话变量session variable
用户变量
用户定义
局部变量 (存储程序中声明的变量)
用户定义,只在存储程序内部有效
查看服务器上有哪些系统变量
show [global | session] variables;
show global variables # 查看全局变量
show session variables # 查看会话变量
show variables; #不写,默认为session级别
Like模糊匹配查看系统变量
show [global | session] like ‘%变量名%’;
查看指定系统变量的值
select @@[global. | session.] 系统变量名;
系统变量以@@为前缀,不指定类型
常见系统全局变量
| 全局变量名称 | 说明 |
|---|---|
| @@back_log | MySQL主要连接请求的数量 |
| @@basedir | MySQL安装基准目录 |
| @@license | 服务器的许可类型 |
| @@port | 服务器侦听TCP/IP连接所用端口 |
| @@storage_engine | 存储引擎 |
| @@version | 服务器版本号 |
赋值(修改系统变量取值)
set [global | session] 系统变量名=值;
set @@[global. | session.] 系统变量名=值;
用户变量声明并初始化
set @变量名 = 值;
set @变量名 := 值;
select @变量名 := 值;
以@为前缀,不指定类型
声明时必须初始化
赋值(或用户变量值更新)
set @变量名 = 值;
set @变量名 := 值;
select @变量名 := 值;
select 属性 into @变量名 from 表名;
局部变量声明
declare 变量名 变量类型;
declare 变量名 变量类型 [default 默认值];
局部变量前面没有@符号
局部变量赋值
set 局部变量名 = 值;
set 局部变量名 := 值;
select 局部变量名 := 值;
select 属性 into 局部变量名 from 表名;
使用(查看变量值)
select 局部变量名;
存储函数function
定义函数
CREATE FUNCTION 函数名([参数名 参数数据类型[,…]])
RETURNS 返回值的数据类型
[函数选项]
BEGIN
函数体;
RETURN 语句;
END
函数选项
DETERMINISTIC:用于指示该程序具有确定性。也就是说,如果给定相同的输入,程序将始终产生相同的输出;
NO SQL:用于指示该程序将不会读取或更改任何数据库表(或数据);
READS SQL DATA:表示程序将读取数据库表;不同于NO SQL,因为如果程序读取数据,则 MySQL需要将其缓存,并在每次调用程序时更新缓存。
调用函数
SELECT 函数名([参数值[,…]]);
删除函数
DROP FUNCTION 函数名;
查看定义的函数
SHOW FUNCTION STATUS;
SHOW FUNCTION STATUS LIKE ‘%func%’;
SHOW FUNCTION STATUS WHERE db=’company’;
查看函数的创建语句
SHOW CREATE FUNCTION 函数名;
流程控制语句
分支语句
if-then-else
IF 条件 THEN SQL语句块1;
[ELSEIF 条件2 THEN SQL语句块2;]
[ELSE SQL语句块2; ]
END IF;
case-when-then
CASE 表达式
WHEN 表达式返回值1 THEN SQL语句块1
WHEN 表达式返回值2 THEN SQL语句块2
……
WHEN 表达式返回值n THEN SQL语句块n
[ELSE SQL语句块n+1]
END CASE
CASE
WHEN 条件1 THEN SQL语句块1
WHEN 条件2 THEN SQL语句块2
……
WHEN 条件n THEN SQL语句块n
ELSE SQL语句块n+1
END CASE
循环语句
LOOP
[<标签>:] loop
<SQL 语句块>
if 条件表达式 then leave [<标签>];
END if;
END loop [<标签>];
使用LEAVE子句跳出循环
标签:可以用来标记一个LOOP语句
WHILE
[<标签>:] while <条件表达式> DO
<SQL 语句块>
END while [<标签>];
REPEAT
[<标签>:] repeat
<SQL 语句块>
until <条件表达式>
END repeat [<标签>];
可嵌套使用
存储过程procedure
存储程序(stored program)
为了便于代码维护,提高代码复用性,将频繁使用的业务逻辑封装成存储程序,被数据库服务器所存储和执行,包含四类:
Functions 函数
Stored procedures 存储过程
Triggers 触发器
Events 事件
创建存储过程
CREATE PROCEDURE 存储过程名(
[IN|OUT|INOUT] 参数1 数据类型,
[IN|OUT|INOUT] 参数2 数据类型,
……)
[存储过程选项] #同函数选项
BEGIN
过程体;
END
调用存储过程
CALL 存储过程名();
删除存储过程
DROP PROCEDURE 存储过程名;
查看创建的存储过程
SHOW PROCEDURE STATUS; ## 查询数据库服务器上定义的所有存储过程
show procedure status where db=‘company’; ## 查询某个数据库上定义的存储过程
SHOW PROCEDURE STATUS LIKE ‘%emp%’; ## 模糊匹配查询
触发器trigger
触发器是用户定义在关系表上的一类由事件驱动的特殊过程
定义的触发器存储在数据库服务器中
事件驱动:指定的数据更新操作,包括:Insert; delete; update
定义触发器
DELIMITER $
CREATE TRIGGER <触发器A>
[BEFORE|AFTER] [INSERT|UPDATE|DELETE] ON <表名>
FOR EACH ROW
[FOLLOWS|PRECEDES] <触发器B>
BEGIN
<触发器主体>
END$
DELIMITER ;
命名约定格式
同一表上定义的触发器,命名要互不相同;不同表上定义的触发器,命名可以相同。
推荐采用以下格式:
(BEFORE | AFTER)tableName_(INSERT| UPDATE | DELETE)
或 tablename_(BEFORE | AFTER)__(INSERT| UPDATE | DELETE)
触发器执行顺序
FOLLOWS <触发器B>:在触发器B之后执行
PRECEDES <触发器B>:在触发器B之前执行
碎碎念
MySQL 5.7.2+开始,可以为同一触发事件和时间定义多个触发器
MySQL版本5.1.4开始,触发器可以调用存储过程或存储函数
REPLACE 或 LOAD DATA语句调用了insert,也会激活表关联的触发器
查看触发器
SHOW TRIGGERS [FROM|IN] 数据库名 [LIKE expr | WHERE expr];
SHOW TRIGGERS; #查看当前数据库中的触发器
SHOW TRIGGERS FROM mysqldemo; #查看数据库mysqldemo中的触发器
SHOW TRIGGERS FROM mysqldemo WHERE ‘table’ = ‘employees’; # 查看employees表的触发器
删除触发器
DROP TRIGGER [ IF EXISTS ] [数据库名] <触发器名>
例如:DROP TRIGGER before_products_update_2;
修改触发器
先删除,再重建
查看给定数据库中的触发器
SELECT *
FROM information_schema.triggers
WHERE trigger_schema = ‘数据库名’;
查看数据库中特定表的触发器
SELECT *
FROM information_schema.triggers
WHERE trigger_schema = ‘数据库名’
AND event_object_table = ‘表名’;
游标cursor
程序设计语言不能处理以集合形式返回的数据,SQL提供游标(Cursor)机制,一行一行地遍历查询结果
游标通常在存储过程或函数中使用
一次定义,多次使用
一个begin end中只能声明一个游标
游标中有个指针,打开游标时,才会执行游标中的select语句,这时该指针会指向select结果中的第一行记录
游标声明
DECLARE 游标名 CURSOR FOR SELECT_语句;
游标必须声明在变量声明之后,并始终与SELECT语句关联
打开游标
OPEN 游标名;
遍历数据
FETCH 游标名 INTO 变量列表;
获取一行数据并同时将游标移到下一行
如果当前行无数据,会引发mysql内部的NOT FOUND错误
关闭游标
CLOSE 游标名;
NOT FOUND 声明
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
fetch找不到数据时执行的动作
