mysql的sql编程
sql编程
变量
变量分为两种:系统变量和自定义变量
系统变量
系统定义好的变量:大部分的时候用户根本不需要使用系统变量,系统变量时用来控制服务器的表现的,如:auto_commit.
查看系统变量
show variable
查看具体变量值:
任何一个有数据访问的内容都是由select查看
select @@系统变量名;
修改系统变量:
分为两种方式:会话级别,全局级别
会话级别:临时修改,仅在当前会话有效
set 变量名 = 值;
set @@变量名 = 值;
全局级别:一次修改,永久生效(对所有客户端都生效)
set global 变量名 = 值;
自定义变量
用户自己定义的变量
系统为了区分系统变量。规定用户自定义变量必须使用一个@符号
set @变量名 = 值;
在mysql中,"="会被当成比较作用处理,为了区分,mysql重新定义了一个赋值符号: :=
mysql允许从数据库表中获取数据然后赋值给变量
方案1:边赋值边查看结果
select @变量名 = 字段名 from 数据源;
方案2:只赋值不看结果,要求只能查询结果为1条数据。
select 字段列表 from 数据源 into 变量列表
注意:
所有自定义变量都是会话级别,当前客户端当次连接有效
所有的自定义变量不区分数据库(用户级别)
需求:
有两张表,一张订单表,一张商品表,没生成一个订单,意味着商品的库存要减少
触发器:
trigger,事先为某张表绑定好一段代码,当表中的某些内容发生改变的时候(增删改),系统会自动触发代码,执行。
触发器:事件类型,触发事件,触发对象
事件类型:增删改,三种类型 :insert,delete,update
触发事件:前后:before ,after
触发对象:表中的每一条记录
一张表中不能具有相同触发时间触发类型的触发器:也就是一张表中最多有6种触发器
创建触发器:
在mysql中:没有大括号,没有小括号,都是用对应的字符符号代替。
触发器基本语法:
-- 临时修改语句结束符号
delimiter 自定义符号 -- 后续遇到该符号才算结束
create trigger 触发器名字 触发时间 触发类型 on 触发对象 for each row
begin -- 代表大括号,开始
-- 触发器的内容,
end -- 代表大括号,结束
-- 语句结束符
自定义符号;
-- 将语句结束符修改回去
delimiter ;
例子:
delimiter $$
create trigger after_order after insert on my_order for each row
begin
update my_goods set inv = inv - 1 where id = 2;
end
$$
delimiter ;
如果是在编辑器中,不需要使用delimiter。我使用的是sql front。
我的代码:
create trigger after_order_add
after insert
on my_order
for each row
begin
update my_goods set inv=inv-1 where id =1;
end;
查看触发器
查看所有触发器或模糊匹配
show triggers [like 'pattern']
查看触发器创建语句
show create trigger 触发器名字
show create trigger after_order
所有的触发器都会保存在一张系统表中 information_schema.triggers
修改触发器&删除触发器
触发器不能修改只能先删除再新增
删除触发器
drop trigger 触发器名
触发器记录:
不管触发器是否触发了,只要当某种操作准备执行,系统就会将当前要操作的记录的当前状态和即将执行之后的新的状态分别保留下来供触发器使用。
其中要操作当前状态保存在old中
操作后的可能形态保存在new中
有点类似事务。
使用方式:
old.字段名 / new.字段名(new 代表的是假设发生之后的结果)
分支结构
分支结构:实现准备多个代码块,按照条件选择性执行某段代码
在mysql中只有if分支
基本语法:
if 条件判断 then
-- 满足条件要执行的代码;
else
-- 不满足条件要执行的代码;
end if;
循环结构
循环结构:某段代码在指定条件内重复执行。
While循环(没有for循环)
Where 条件判断 do
-- 满足条件要执行的代码
-- 变更循环条件
End While;
循环控制:在循环内部进行循环判断和控制
Mysql中没有对应conrinue和break,但是有替代品。
Iterate:迭代,类似continue,后面的代码不执行,循环重新来过
Leave:离开,类似break整个循环结束
使用方式:Iterate/leave 循环名字;
-- 定义循环名字
循环名字:while 条件 do
-- 循环体
-- 循环控制
Leave/iterate 循环名字;
End while;
函数
函数:将一段代码封装到一个结构中,在需要执行代码块的时候,调用结构执行即可(代码复用)
函数分为两类:系统函数和自定义函数
系统函数:
系统定义好的函数,直接调用即可
任何函数都有返回值,因此使用select调用。
字符串函数:
mysql中,字符串的基本操作单位(最常见的而是字节)
substring 字符串截取函数
char_length 字符串的字符长
length 字符串的字节长
instr 一个字符串中是否存在另一个字符串
lpad 左填充
insert 字符串替换
strcmp 字符串比较
自定义函数:
函数要素:函数名,参数列表(形参和实参),返回值,函数体(作用域)
创建函数:
create function 函数名([形参列表]) returns 数据类型 -- 规定要返回的数据类型
Begin
-- 函数体
-- 返回值:return 类型(指定数据类型);
end;
调用函数:
select cs();
删除函数:
drop function 函数名
函数形参:
参数分为两种:定义时的参数叫形参,调用时的参数叫实参(实参可以是数值也可以是变量)
形参:要求必须指定数据类型
Function 函数名(形参名字 字段类型) returns 数据类型
作用域:
Mysql中的作用域与js中的作用域完全一样
全局变量可以在任何地方使用,局部变量只能在函数体内使用
全局变量:
使用set关键字定义,使用@符号标志
局部变量:
使用declare关键字声明,没有@符号。所有的局部变量声明,都必须在函数体开始之前。
存储过程
存储过程简称过程,procedure,是一种用来处理数据的方式
存储过程是一种没有返回值的函数
创建过程
create produce 过程名(参数列表)
begin
-- 过程体
end;
查看过程
函数的查看方式完全适用于过程,关键字换成procedure
查看所有过程:show procedure status [like pattern]
查看过程创建语句:show create procedure 过程名
调用过程:
call 过程名(参数列表);
修改过程&删除过程:
删除过程:drop procedure 过程名;
过程参数:
函数的参数需要数据类型指定,过程比函数更严格。
过程还有自己的类型限定:三种类型
in:数据只是从外部传入给内部使用(值传递):可以是数值也可以是变量
out:只允许过程内部使用(不用外部数据),给外部使用的.(引用传递:特殊之处,外部的数据会被先清空才,才会进入内部操作),只能是变量
inout:外部可以在内部使用,内部修改也可以给外部使用:典型的引用传递,只能传递变量
基本使用:
create procedure 过程名(in 参数名字 数据类型,...)
存储过程对于变量的操作是滞后的:是在存储过程调用结束后,才会重新将变量修改的
对应的sql:
create table usr(
name varchar(50) not null,
age int not null
);
insert into usr values('zhangsan',20);
insert into usr values('lisi',21);
insert into usr values('wangwu',22);
insert into usr values('zhaoliu',23);
insert into usr values('shengqi',24);
-- 查看所有系统变量
SHOW VARIABLES;
-- 查看系统变量值
SELECT
@@autocommit, @@version;
-- session级修改系统变量
SET `autocommit` = 0;
SET @@autocommit = 0;
-- 修改全局系统变量
SET GLOBAL `autocommit` = 0;
SET GLOBAL `autocommit` = 1;
-- 定义自定义变量
set @name = '张三';
-- 为了区分=的比较作用,mysql可以这样赋值
set @age := 18;
-- 查看自定义变量
select @name;
select @age;
-- 边赋值边看结果,赋值为了与比较区分只能使用:=,最终变量的值是最后一次执行语句时字段的值
select @name := name ,name from usr;
-- 只赋值不看结果,查询语句只能查询出一条结果
select name ,age from usr where name = 'zhangsan' into @name ,@age;
create table my_goods(
id int primary key auto_increment,
name varchar(20) not null,
price decimal(10 , 2) default 1,
inv int comment '库存数量'
)charset utf8;
insert into my_goods values(null , 'iPhone6s' , 5288 , 100);
insert into my_goods values(null , 'vivo' , 3200 , 100);
create table my_order(
id int primary key auto_increment,
g_id int not null comment '商品ID',
g_number int comment '商品数量'
)charset utf8;
select * from my_goods;
-- 创建触发器
create trigger after_order_add
after insert
on my_order
for each row
begin
update my_goods set inv=inv-1 where id =1;
end;
-- 测试触发器使用
insert into my_order values(null , 1 , 2);
select * from my_order;
select * from my_goods;
-- 查询触发器
show triggers;
show create trigger after_order_add;
-- 查看触发器表
select * from information_schema.triggers;
-- 删除触发器
drop trigger after_order_add;
-- 解决刚才触发器的不准确问题
create trigger after_order
after insert
on my_order
for each row
begin
update my_goods set inv = inv-new.g_number where id = new.g_id;
end;
-- 测试触发器使用
insert into my_order values(null , 1 , 2);
select * from my_order;
select * from my_goods;
-- 这个时候会发现另一个问题,就是触发器如果删除得成负数,那是有问题的。
-- 触发器结合if分支,判断商品库存是否足够,不够不能生成订单
create trigger before_order
before insert
on my_order
for each row
begin
select inv from my_goods where id = new.g_id into @inv;
if
@inv < new.g_number
then
-- 库存不够,触发器没有提供一个阻止语句执行的方法,所以报错暴力终止
insert into xxx values(xxx);
end if;
end;
insert into my_order values(null , 1 , 3);
-- 定义两个变量
set @cn = '世界你好';
set @en = 'hello world';
select substring(@cn,1,1),substring(@en,1,1); -- 世 h ,字符串下表从1开始,以字节为单位
select char_length(@cn),char_length(@en),length(@cn),length(@en); -- 4 ,11 , 12 ,11 我的是utf-8编码
select instr('hello','he'),instr('hello','s'); -- 1 , 0
select lpad(@cn , 20, '欢迎'),lpad(@en , 20 , 'hello');
select insert('hello world' , 3 , 3 ,'y'); -- key world
set @fi = 'hello';
set @se = 'key';
set @th = 'KEY';
SELECT strcmp(@fi , @se), strcmp(@se , @th), strcmp(@th , @fi); -- -1, 0 , 1 字符串不区分大小写在SQL中
create trigger after_order
after insert
on my_order
for each row
begin
update my_goods
set
inv = (inv - new.g_number)
where
id = new.g_id;
end; insert into my_order values(null , 1 , 2);
select * from my_goods;
select * from my_order; -- 这个时候会发现另一个问题,就是触发器如果删除得成负数,那是有问题的。 -- 触发器结合if分支,判断商品库存是否足够,不够不能生成订单 create trigger before_order
before insert
on my_order
for each row
begin
select inv from my_goods where id = new.g_id into @inv;
if
@inv < new.g_number
then
-- 库存不够,触发器没有提供一个阻止语句执行的方法,所以报错暴力终止
insert into xxx values(xxx);
end if;
end; insert into my_order values(null , 1 , 3); -- 系统函数
-- 定义两个变量
set @cn = '世界你好';
set @en = 'hello world'; select substring(@cn,1,1),substring(@en,1,1); -- 世 h ,字符串下表从1开始,以字节为单位 select char_length(@cn),char_length(@en),length(@cn),length(@en); -- 4 ,11 , 12 ,11 我的是utf-8编码 select instr('hello','he'),instr('hello','s'); -- 1 , 0 select lpad(@cn , 20, '欢迎'),lpad(@en , 20 , 'hello'); select insert('hello world' , 3 , 3 ,'y'); -- key world set @fi = 'hello';
set @se = 'key';
set @th = 'KEY';
SELECT strcmp(@fi , @se), strcmp(@se , @th), strcmp(@th , @fi); -- -1, 0 , 1 字符串不区分大小写在SQL中 -- 自定义函数
create function cs() returns varchar(50)
begin
return "hello world";
end;
-- 调用函数
select cs(); -- 查看函数 【like pattern】 -- 函数从属于数据库
show function status like 'cs'; -- 查看函数的创建语句
show create function cs; -- 修改函数 & 删除函数
-- 函数只能先删除后新增,不能修改
drop function cs; -- 做函数,计算1~n的累加
create function add1(n int) returns int
begin
set @i = 1;
set @res = 0;
while @i <= n do
set @res = @res + @i;
set @i = @i + 1;
end while;
return @res;
end; select add1(3);
-- 在函数内部定义的变量在函数外部也可以访问
select @res; -- 求和,1~n之间的数之和,5的倍数不加
create function add2(n int) returns int
begin
declare i int default 1;
declare res int default 0;
w1: while i <= n do
if i%5 = 0 then
set i = i + 1;
iterate w1;
else
set res = res + i ;
set i = i + 1;
end if;
end while;
return res;
end; select add2(5); -- 创建存储过程
create procedure p1()
begin
select * from my_goods; -- 假设过程中需要显示数据,使用select
end; -- 调用过程
call p1(); -- 查看过程
show procedure status like 'p1';
-- 查看过程创建语句
show create procedure p1; -- 过程参数
create procedure p2(in var1 int , out var2 int , inout var3 int)
begin
select var1,var2,var3; -- var2的值一定是null,进入过程前会清除值
end; -- call p2(1,2,3); in和inout参数只能传递变量而不能是值
set @int_1 = 1;
set @int_2 = 2;
set @int_3 = 3; select @int_1,@int_2,@int_3; -- 1,2,3
call p2(@int_1,@int_2,@int_3); -- 1, null, 3
select @int_1,@int_2,@int_3; -- 1, null , 3 -- out 和inout属于引用数据类型:内部修改会影响外部
-- 存储过程执行结束后,mysql将传入的引用变量修改后的值返回给实参。
mysql的sql编程的更多相关文章
- 《[MySQL技术内幕:SQL编程》读书笔记
<[MySQL技术内幕:SQL编程>读书笔记 2019年3月31日23:12:11 严禁转载!!! <MySQL技术内幕:SQL编程>这本书是我比较喜欢的一位国内作者姜承尧, ...
- sql编程小结
对照mysql5.1手册,对这几天学的sql编程进行小结,主要涉及触发器.存储过程.权限管理.主从分离等,权当抛砖引玉,高手请略过. 一.触发器 通俗的说就是在指定的数据表增删改的前或后触发执行特定的 ...
- ORACLE PL/SQL编程详解
ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...
- MySQL与SQL比较有那些区别呢
MySQL是一个逐渐完善的过程,使用前期版本时会遇到一些问题,通常搞得莫名其妙,在版本选择上尽量选择最新的. 1.在5.03以前版本中,存储varchar型数据时,后面的空格会被忽视掉,前面的空格会保 ...
- The MySQL C API 编程实例
在网上找了一些MYSQL C API编程的文章,看了后认为还是写的不够充分,依据自己经验写了这篇<The MySQL C API 编程实例>,希望对须要调用到MYSQL的C的API的朋友有 ...
- SQL编程之生日问题
在学习MySQL的时候,一个较为经典的SQL编程题目就是生日问题,已知某个用户的出生日期和当前日期,计算他近期的生日. 一般须要考虑两个问题 闰年2月是29天 今年的生日是否过完 比如:某人的生日是1 ...
- sql编程 && 存储过程
sql 结构化查询语言 是一种编程语言 用于管理数据库的编程语言 元素: 数据 数据类型 变量的数据类型 就是字段的数据类型 变 ...
- mysql中SQL执行过程详解与用于预处理语句的SQL语法
mysql中SQL执行过程详解 客户端发送一条查询给服务器: 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果.否则进入下一阶段. 服务器段进行SQL解析.预处理,在优化器生成对应的 ...
- 实验5 Spark SQL编程初级实践
今天做实验[Spark SQL 编程初级实践],虽然网上有答案,但都是用scala语言写的,于是我用java语言重写实现一下. 1 .Spark SQL 基本操作将下列 JSON 格式数据复制到 Li ...
随机推荐
- [NOI2014]动物园(kmp)
题目 https://www.luogu.org/problemnew/show/P2375 做法 查找多少个前缀与后缀配对,其实就是\(fail\)树的深度 而不可重叠,其实\(i\)不可用的,\( ...
- CSS 图片
CSS 图片 一.圆角图片 img { border-radius: 8px; } 二.缩略图 border 属性来创建缩略图. img { border: 1px solid #ddd; borde ...
- docker使用Mesos
https://github.com/PyreneGitHub/mesos_use/tree/master
- 20145324Java课程总结
20145324课程总结 ●每周读书笔记链接总汇 [第一周](http://www.cnblogs.com/SJZGM10/p/5246770.html) 第二周(不小心删了) [第三周](http: ...
- 如何退出minicom【学习笔记】
一.先按ctr+a进入设置模式 二.在按x退出
- [BZOJ1044木棍分割]
Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连 接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段 ...
- 多线程资源隔离之ThreadLocal
上篇讲到多线程线程安全问题的解决思路,这篇将详细讲解资源隔离ThreadLocal的实践. ThreadLocal也叫线程局部变量,类似Map结构,以当前线程为key.既然是以资源隔离的思想保证线程安 ...
- TSP - 状态压缩dp
2017-08-11 21:10:21 艾教写的 #include<iostream> #include<cstdio> #include<cstring> #in ...
- java23种设计模式之三: 适配器模式
一.适配器模式 就是个通过一个中间件转化,可以将不匹配的两件事整合到一起,把不匹配变的匹配. 二.适配器分类 1.类适配器 2.对象适配器 三. 适配器的3种组成 1.类适配器组成 1.2个接口 ...
- mkdir: 无法创建目录"": 没有那个文件或目录
# mkdir /data/backup/20181128 mkdir: 无法创建目录"/data/backup/20181128": 没有那个文件或目录 原因是data目录不存在 ...