数据库相关语法
视图:
视图:虚拟表。
注意:修改虚拟表,原表也会发生改变。解决方式:创建子账号,子账号只有查询权限。
场景:
sql
# 创建移动公司的用户表
CREATE TABLE user(
username VARCHAR(32) PRIMARY KEY,
password VARCHAR(32),
name VARCHAR(32),
type INT(3),
province VARCHAR(32),
city VARCHAR(32),
phone VARCHAR(32),
age INT(3)
)
create [or replace] view 视图名 as select 字段名 from 表名 where 条件 [with check option]
sql
# 创建视图
create or replace view view01 as select phone,province,city,age from user where age < 40 with check option;
or replace 如果视图名相同就替换。
with check option修改数据时如果违反条件就不允许修改。
sql
# 查询视图数据
SELECT * FROM view01;
sql
# 修改视图数据
UPDATE view01 SET age=41 WHERE phone='13993300090';
sql
# 删除视图数据
DELETE FROM view01 WHERE phone='13993300090';
sql
# 删除视图
DROP view view01;
触发器:
场景:
sql
# 创建学科表,并添加数据
CREATE TABLE course(
id INT(3) PRIMARY KEY auto_increment,
name VARCHAR(32),
sum INT(3) DEFAULT 0
)
INSERT INTO course(name) VALUES('JavaEE');
INSERT INTO course(name) VALUES('Python');
INSERT INTO course(name) VALUES('HTML');
# 创建班级表,并添加数据
CREATE TABLE class(
id INT(3) PRIMARY KEY auto_increment,
name VARCHAR(32),
sum INT(3) DEFAULT 0
)
INSERT INTO class(name) VALUES('JavaEE01');
INSERT INTO class(name) VALUES('JavaEE02');
INSERT INTO class(name) VALUES('Python01');
INSERT INTO class(name) VALUES('Python02');
INSERT INTO class(name) VALUES('HTML01');
INSERT INTO class(name) VALUES('HTML02');
# 创建学生表
CREATE TABLE student(
id INT(3) PRIMARY KEY auto_increment,
name VARCHAR(32),
class_id INT(3),
course_id INT(3)
)
应用:
需求:添加学生,并更新班级表和学科表的数据。
sql
# 创建触发器(添加学生数据之后,就会触发班级表和学科表更新数据的操作)
delimiter xx
create trigger tri01 after insert on student for each row
BEGIN
UPDATE class SET sum=sum+1 WHERE id=new.class_id;
UPDATE course SET sum=sum+1 WHERE id=new.course_id;
END xx
delimiter ;
INSERT INTO student(name,class_id,course_id) VALUES('小明',1,1);
INSERT INTO student(name,class_id,course_id) VALUES('小黑',1,1);
INSERT INTO student(name,class_id,course_id) VALUES('小俊',2,1);
INSERT INTO student(name,class_id,course_id) VALUES('小希',3,2);
INSERT INTO student(name,class_id,course_id) VALUES('小空',4,2);
delimiter xx - 设置SQL命令的结束符。
trigger - 触发器
after - 后置触发
需求:删除学生,并更新班级表和学科表的数据。
sql
# 创建触发器(删除学生数据之前,就会触发班级表和学科表更新数据的操作)
delimiter xx
create trigger tri02 before delete on student for each row
BEGIN
UPDATE class SET sum=sum-1 WHERE id=old.class_id;
UPDATE course SET sum=sum-1 WHERE id=old.course_id;
END xx
delimiter ;
DELETE FROM student WHERE id = 2;
sql
# 删除触发器
DROP TRIGGER tri01;
DROP TRIGGER tri02
存储过程:
存储过程:类似于Java里的方法。
SQL中存储过程 与 Java中方法 的区别:Java方法中的参数指的是外界传入到方法内部的数据,返回值指定是方法结束后返回的具体数据,SQL存储过程中没有返回值,但是有返回参数。
存储过程中参数的分类: in - 传入参数
out - 传出参数
inout - 传入传出参数
场景:
sql
# 创建学生表,并添加数据
CREATE TABLE student(
id INT(3) PRIMARY KEY auto_increment,
name VARCHAR(32),
sex VARCHAR(32),
age INT(3),
salary FLOAT(8,2),
course VARCHAR(32)
)
INSERT INTO student(name,sex,age,salary,course) VALUES('小俊','男',23,10000,'Java');
INSERT INTO student(name,sex,age,salary,course) VALUES('小明','男',20,12000,'Java');
INSERT INTO student(name,sex,age,salary,course) VALUES('小燕','女',19,17000,'Java');
INSERT INTO student(name,sex,age,salary,course) VALUES('小华','男',21,15000,'Java');
INSERT INTO student(name,sex,age,salary,course) VALUES('小德','男',27,10000,'Java');
INSERT INTO student(name,sex,age,salary,course) VALUES('小建华','男',19,12000,'Java');
INSERT INTO student(name,sex,age,salary,course) VALUES('小宇','男',32,5000,'Python');
INSERT INTO student(name,sex,age,salary,course) VALUES('黄华','男',45,4000,'Python');
INSERT INTO student(name,sex,age,salary,course) VALUES('达华','男',28,7000,'Python');
INSERT INTO student(name,sex,age,salary,course) VALUES('小华小','男',30,8000,'Python');
INSERT INTO student(name,sex,age,salary,course) VALUES('小小小华','男',23,12000,'Python');
INSERT INTO student(name,sex,age,salary,course) VALUES('小希','女',30,7000,'HTML');
INSERT INTO student(name,sex,age,salary,course) VALUES('小空','女',23,6000,'HTML');
INSERT INTO student(name,sex,age,salary,course) VALUES('小阳','女',28,8000,'HTML');
应用:
sql
# 最简单的存储过程
# 查询学生表和用户表里的数据
delimiter xx
CREATE PROCEDURE pro01()
BEGIN
SELECT * FROM student;
SELECT * FROM user;
END xx
delimiter ;
sql
# 调用存储过程
CALL pro01();
需求:创建存储过程,传入学生id,查询出学生姓名。
sql
delimiter xx
CREATE PROCEDURE pro02(IN s_id INT(3))
BEGIN
SELECT name FROM student WHERE id=s_id;
END xx
delimiter ;
# 调用存储过程
CALL pro02(2);
需求:创建存储过程,传入学生id,返回学生姓名。
sql
delimiter xx
CREATE PROCEDURE pro03(IN s_id INT(3),OUT s_name VARCHAR(32))
BEGIN
SELECT name INTO s_name FROM student WHERE id=s_id;
END xx
delimiter ;
# 调用存储过程
CALL pro03(3,@s_name);
SELECT @s_name;
需求:创建存储过程,传入学生id,返回学生年龄。
sql
delimiter xx
CREATE PROCEDURE pro04(INOUT param INT(3))
BEGIN
SELECT age INTO param FROM student WHERE id=param;
END xx
delimiter ;
# 调用存储过程
SET @param = 3;
CALL pro04(@param);
SELECT @param;
删除存储过程。
sql
# 删除存储过程
DROP PROCEDURE pro01;
DROP PROCEDURE pro02;
DROP PROCEDURE pro03;
DROP PROCEDURE pro04;
函数:
预定义函数:
预定义函数:MySQL给我们提供的函数。
注意:函数必须有返回值。
数学类函数:
sql
SELECT ABS(-100);# 求绝对值
SELECT sqrt(9); # 求平方根
SELECT mod(10,3);# 求余数
SELECT pow(2,3); # 求次方
SELECT rand();# 求随机值
字符串类函数 :
sql
SELECT CONCAT("今天阳光真好","我们正当年少");# 拼接字符串
SELECT SUBSTR("今天阳光真好",2,2);# 截取字符串(目标字符串,第几个字符,截取长度)
SELECT length("今天阳光真好");# 获取长度(字节)
日期时间类函数:
sql
SELECT now();# 获取当前日期时间
SELECT YEAR(NOW());# 获取年
SELECT MONTH(NOW());# 获取月
SELECT DAYOFMONTH(NOW());# 获取日
SELECT HOUR(NOW());# 获取时
SELECT MINUTE(NOW());# 获取分
SELECT SECOND(NOW());# 获取秒
SELECT DATE_FORMAT(NOW(),"%Y年%m月%d日 %H时%i分%s秒");
自定义函数:
MySQL的函数必须有返回值。
求:创建一个函数,传入学生id,返回学生信息。
sql
delimiter xx
CREATE FUNCTION fun(s_id INT(3)) RETURNS VARCHAR(32) DETERMINISTIC
BEGIN
#声明变量
DECLARE s_name VARCHAR(32);
SELECT name INTO s_name FROM student WHERE id=s_id;
RETURN s_name;
END xx
delimiter ;
sql
# 调用函数
SELECT fun(3);
sql
# 删除函数:
drop function fun;
范式:
第一范式:
第一范式:
- 有严重的数据冗余问题。
- 数据添加存在问题:添加新开设的系名和系主任时,数据不合法。
- 数据删除存在问题:罗志祥同学毕业了,删除数据,会将系的数据一起删除。
第二范式:
第二范式:
- 解决了数据冗余问题。
- 数据添加存在问题:添加新开设的系名和系主任时,数据不合法。
- 数据删除存在问题:罗志祥同学毕业了,删除数据,会将系的数据一起删除。
第三范式:
第三范式:
- 存在非常严重的数据冗余(重复)。(已解决)
- 数据添加问题,数据不合法 。(已解决)
- 数据删除问题,删除数据,会将系的数据一起删除。 (已解决)
反范式设计:
多表关联在查询时会消耗较多的时间,使用反范式设计会存在数据的冗余,但是减少了表的存在,也就是说牺牲了空间换取更多的时间。