数据库系统(六)---MySQL语句及存储过程
一、DDL、DML、DCL常用语句
1、DDL(Data Definition Language)数据库定义语言
(1)数据库模式定义
#创建数据库 create database if exsites db_name; #选定数据库 use db_name; #删除数据库 drop database if exists db_name; #修改数据库 alter database db_name set ...; #展示所创建的数据库 show databases; #统计mysql中某个数据库中的表的数量 SELECT count(*) TABLES, table_schema FROM information_schema.TABLES where table_schema = 'mysql中数据库名称' GROUP BY table_schema;
(2)表定义
#创建表 create table test_table ( s_id int not null auto_increment, s_name char(50) not null default "hanmei", s_age int not null, primary key(s_id), index index_name(s_name) ); #添加外键 alter table B add constraint `bfk` foreign key ('fk_column_name') references A('column_name') on delete no action on update no action; #删除外键 alter table B drop foreign key `bfk`; #删除表 drop table if exists test_table; #展示表结构 desc test_table; #修改表结构的操作 1、添加表字段 alter table 表名 add 字段名 类型(值) eg:alter table user add name varchar(40); 2、删除表字段 alter table 表名 drop 字段名 eg: alter table user drop name; 3、字段名更名 alter table 表名 rename 老字段名 to 新字段名 eg:alter table user rename oldname to newname; 4、更改字段类型 alter table 表名 alter 字段 类型; eg:alter table user alter name varchar(50); 5、修改表名 alter table 表名 rename to 新表名; eg:alter table test001 rename to test002;
2、DML(data manipulation language)数据库操作语言
insert into test_table(s_age) values(18); insert into test_table set s_age=19; #插入部分列值数据
#case...when 匹配条件 select s_name as name,s_sex case when 'f' then ‘女’ else '男' end as sex from test_table; #使用内置函数 select count(*) from customers; select max(cust_id) from customers; select min(cust_id) from customers; select sum(cust_id) from customers; select avg(cust_id) from customers;
#比较运算符
select * from customers where cust_id!=2; select * from customers where cust_id<>2;
#逻辑运算符
#---and 与
select * from customers where cust_id>2 and cust_sex=1;
#---or 或
select * from customers where cust_id>2 or cust_sex=1;
#两者之间 范围
select * from customers where cust_id between 2 and 4;
select * from customers where cust_id>=2 and cust_id<=4;
#in
select * from customers where cust_id in(2,4);
select * from customers where cust_id=2 or cust_id=4;
#子查询
select * from stu_info where sno in(select sno from stu_score);
#分组查询
select ssex,count(*)from stu_info group by ssex;
select saddress,ssex,count(*) from stu_info group by saddress,ssex;
select saddress,ssex,count(*) from stu_info group by saddress,ssex with rollup;
#having 筛选---过滤分组后的数据
-
HAVING
用于对汇总的GROUP BY
结果进行过滤。 -
HAVING
要求存在一个GROUP BY
子句。 -
WHERE
和HAVING
可以在相同的查询中。 -
HAVING
vsWHERE
-
WHERE
和HAVING
都是用于过滤。 -
HAVING
适用于汇总的组记录;而 WHERE 适用于单个记录。
select saddress,ssex ,count(*) from stu_info group by saddress,ssex having count(*)>1;
补充:
limit start,pageSize; eg: SELECT * FROM table as t order by t.id LIMIT 0,10; //删除数据 DELETE FROM tb_courses_new; DELETE FROM tb_courses WHERE course_id=4; inert ...select...; #INSERT INTO SELECT 语句从一个表复制数据,然后把数据插入到一个已存在的表中。 eg: INSERT INTO table2 SELECT * FROM table1; #从一个表中复制所有的列插入到另一个已存在的表中 INSERT INTO table2(column_name(s)) SELECT column_name(s) FROM table1; #我们可以只复制希望的列插入到另一个已存在的表中 create table ... select...;//从一个表中复制数据,然后新建一个表,并复制到该表中 eg: create table newTable select * from oldTable;
2.1扩展函数
#---文本处理函数 LEFT()、RIGHT() 左边或者右边的字符 LOWER()、UPPER() 转换为小写或者大写 LTRIM()、RTIM() 去除左边或者右边的空格 LENGTH() 长度 SOUNDEX() 转换为语音值 #---时间日期函数 Now() 返回当前日期和时间 #---数值处理函数 AVG() 返回某列的平均值 COUNT() 返回某列的行数 MAX() 返回某列的最大值 MIN() 返回某列的最小值 SUM() 返回某列值之和 注:AVG() 会忽略 NULL 行
2.2 DML之多表关联查询
#交叉连接(笛卡尔积) select * from tb1 cross join tb2; #---内连接 select * from stu_info inner join stu_score on stu_info.sno=stu_score.sno; <=等价写法=> #---注,此处如果没有where条件,查询结果相当于笛卡尔积 select * from stu_info,stu_score where stu_info.sno=stu_score.sno; #---左外连接 select stu_info.sno,stu_info.sname,stu_score.sscore from stu_info left join stu_score on stu_info.sno=stu_score.sno; #---右外连接 select stu_info.sno,stu_info.sname,stu_score.sscore from stu_score right join stu_info on stu_score.sno=stu_info.sno;
3、DCL(Data Control Language)数据库控制语言
安全与访问控制 -- 查看 mysql 数据库的使用者账号 select user from mysql.user; -- 密码加密 select password(456); -- 创建用户 create user 'zhangsan'@'localhost' identified by '123', 'lisi'@'localhost' identified by password '*531E182E2F72080AB0740FE2F2D68 9DBE0146E04'; -- 删除用户账号 drop user lisi@localhost; -- 重命名 rename user 'zhangsan'@'localhost' to 'wangwu'@'localhost'; -- 修改密码 set password for 'wangwu'@'localhost'='*6B4F89A54E2D27ECD7E8DA05B4AB8FD9D1D8B119'; -- 设置权限 grant select n test1.customers o 'wangwu'@'localhost'; -- 创建两个用户 grant select,update on test1.customers to 'liming'@'localhost' identified by '123', 'huang'@'localhost' identified by '789'; --执行所有数据库操作的权限 grant all on test1.* to 'wangwu'@'localhost'; -- 添加用户的权限 grant create user on *.*to 'wangwu'@'localhost'; -- 权限转移 grant select,update on test1.customers to 'zhou'@'localhost' identified by '123' with grant option; -- 权限撤回 revoke select on test1.customers from 'zhou'@'localhost';
4、sql高级及调优
(1)索引
#---创建索引 create index index_name on table(fild1,filed2) #---创建唯一索引 create unique index index_name on 学生基本情况(姓名)
(2)引擎(mySql)
SHOW ENGINES 查看当前数据库支持的引擎 alter table test engine=innodb; 更改数据库表的引擎 show create table test; 查看创建表格的引擎类别
(3)并发场景下应用
1)排它锁(for update)
当一个事务加入排他锁后,不允许其他事务加共享锁或者排它锁读取,更加不允许其他事务修改加锁的行。
select * from t for update 会等待行锁释放之后,返回查询结果。 select * from t for update nowait 不等待行锁释放,提示锁冲突,不返回结果 select * from t for update wait 5 等待5秒,若行锁仍未释放,则提示锁冲突,不返回结果 select * from t for update skip locked 查询返回查询结果,但忽略有行锁的记录
特点:
- 事务之间不允许其它排他锁或共享锁读取,修改更不允许
- 所有事务中有一个排他锁执行 commit 之后,其它事务才可执行
2)共享锁
- 允许其它事务也增加共享锁读取
- 不允许其它事务增加排他锁 (for update)
- 当事务同时增加共享锁时候,事务的更新必须等待先执行的事务 commit 后才行,如果同时并发太大可能很容易造成死锁
start TRANSACTION SELECT * from t LOCK IN SHARE MODE
IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量);
OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量);
INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量);
mysql> delimiter $$ mysql> CREATE PROCEDURE proc_add_stu(
-> IN sNo INTEGER, -> OUT sid int -> ) mysql> BEGIN #存储过程开始 -> insert into student(s_no) values(sNo); -> SELECT LAST_INSERT_ID() into sid; #将选定列的值直接存储到局部变量中 -> END $$ #存储过程结束 mysql> delimiter; #将语句的结束符号恢复为分号 mysql> call pro_add_stu('0001');
mysql> delimiter $$ mysql> create procedure in_proce(in p_in int) -> begin -> select p_in; -> set p_in=0; #局部变量赋值(begin...和end之间) -> select P_in; -> end$$ mysql> delimiter ; mysql> set @p_in=1; #全局变量@p_in赋值 mysql> call in_param(@p_in); #将全局变量@p_in的值作为参数传递给局部变量p_in +------+ | p_in | +------+ | 1 | +------+ +------+ | P_in | +------+ | 0 | +------+ mysql> select @p_in; #输出全局变量@p_in的结果 +-------+ | @p_in | +-------+ | 1 | +-------+
以上可以看出,p_in 在存储过程中被修改,但并不影响 @p_id 的值,因为前者为局部变量、后者为全局变量。
mysql> delimiter // mysql> create procedure out_proce(out p_out int) -> begin -> select p_out; -> set p_out=2; -> select p_out; -> end -> // mysql> delimiter ; mysql> set @p_out=1; mysql> call out_proce(@p_out); +-------+ | p_out | +-------+ | NULL | +-------+ #因为out是向调用者输出参数,不接收输入的参数,所以存储过程里的p_out为null
+-------+ | p_out | +-------+ | 2 | +-------+ mysql> select @p_out; #输出全局变量(用户变量)结果 +--------+ | @p_out | +--------+ | 2 | +--------+ #调用了out_proce存储过程,输出参数,改变了p_out变量的值
mysql> delimiter $$ mysql> create procedure inout_proce(inout p_inout int) -> begin -> select p_inout; -> set p_inout=2; -> select p_inout; -> end -> $$ mysql> delimiter ; mysql> set @p_inout=1; mysql> call inout_proce(@p_inout); +---------+ | p_inout | +---------+ | 1 | +---------+ +---------+ | p_inout | +---------+ | 2 | +---------+ mysql> select @p_inout; +----------+ | @p_inout | +----------+ | 2 | +----------+ #调用了inout_param存储过程,接受了输入的参数,也输出参数,改变了变量
变量作用域
内部的变量在其作用域范围内享有更高的优先权,当执行到 end。变量时,内部变量消失,此时已经在其作用域外,变量不再可见了,应为在存储过程外再也不能找到这个申明的变量,但是你可以通过 out 参数或者将其值指派给会话变量来保存其值。
mysql > DELIMITER // mysql > CREATE PROCEDURE proc3() -> begin -> declare x1 varchar(5) default 'outer'; -> begin -> declare x1 varchar(5) default 'inner'; -> select x1; -> end; -> select x1; -> end; -> // mysql > DELIMITER ;
条件语句
mysql > DELIMITER // mysql > CREATE PROCEDURE proc2(IN parameter int) -> begin -> declare var int; -> set var=parameter+1; -> if var=0 then -> insert into t values(17); -> end if; -> if parameter=0 then -> update t set s1=s1+1; -> else -> update t set s1=s1+2; -> end if; -> end; -> // mysql > DELIMITER ;
循环语句
mysql > DELIMITER // mysql > CREATE PROCEDURE proc4() -> begin -> declare var int; -> set var=0; -> while var<6 do -> insert into t values(var); -> set var=var+1; -> end while; -> end; -> // mysql > DELIMITER ;
create procedure p1() begin declare id int; declare name varchar(15); -- 声明游标 declare mc cursor for select * from class; -- 打开游标 open mc; -- 获取结果 fetch mc into id,name; -- 这里是为了显示获取结果 select id,name; -- 关闭游标 close mc; end;
#删除已经存在的存储函数 DROP FUNCTION IF EXISTS func_stu; #创建存储函数(声明返回类型为varChar(50)) CREATE FUNCTION func_stu(in_id INT) RETURNS VARCHAR(50) BEGIN DECLARE o_name VARCHAR(50); #声明局部变量 SELECT name INTO o_name FROM tb_stu WHERE id = in_id; #tb_stu指事先创建好的数据库 RETURN o_name; END;
SELECT func_stu(1);
DROP FUNCTION IF EXISTS func_stu;
5、修改存储函数
ALTER FUNCTION func_name [characteristic ...] characteristic: COMMENT 'string' | LANGUAGE SQL | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER }
感谢阅读,如需转载,请注明出处,谢谢!https://www.cnblogs.com/huyangshu-fs/p/11669708.html