语法 : create view [表名] as [查询表的语句]
html
建立两个相互关联的表java
select * from emp; select * from dep;
create view emp_dep_view as select * from emp inner join dep on emp.dep_id=dep.did; show tables; select * from emp_dep_view;
update emp_dep_view set name="BigBob" where name="Bob"; select * from emp_dep_view; select * from emp; alter view emp_dep_view2 as select * from emp where id>4; show tables; select * from emp_dep_view2;
咱们发现修改了视图表, 原来的 emp 表的数据也发生了改变python
drop view emp_dep_view; show tables;
致命的问题:视图是存放到数据库里的,若是咱们程序中的sql过度依赖于数据库中存放的视图,那么意味着,一旦sql须要修改且涉及到视图的部分,则必须去数据库中进行修改,而一般在公司中数据库有专门的DBA负责,你要想完成修改,必须付出大量的沟通成本DBA可能才会帮你完成修改,极其地不方便mysql
delimiter %% # 修改结束符 create trigger [触发器名] [before/after] [insert/update/delete] on [表名] for each row # 表示每往上面建立的表进行指定操做以后就执行下面 "begin...end" 里面的SQL语句 begin [sql 语句] end %% delimiter ; # 将结束符改回来
🥝建立一个往"t01"表内插入记录以前触发"sql"语句的触发器 delimiter %% create trigger tri_before_insert_t01 before insert on t01 for each row begin [SQL语句] end %% delimiter ; 🥝建立一个在"t01"表删除记录以后触发"sql"语句的触发器 delimiter %% create trigger tri_after_delete_t01 after delete on t01 for each row begin [sql语句] end %% delimiter ; 🥝建立一个在对"t01"表修改数据以前就触发"sql"语句的触发器 delimiter %% create trigger tri_before_update_t01 before update on t01 for each row [SQL语句] end %% delimiter ;
🥝准备两张表"cmd"、"error_log" create table cmd( id int primary key auto_increment, user varchar(16) not null, permi char(4) not null, cmd varchar(60) not null, sub_time datetime, success enum("yes","no") not null default "no" ); create table error_log( id int primary key auto_increment, error_cmd varchar(60), error_time datetime ); 🥝建立触发器,当"cmd"表中的"cuccess"字段是"no",那么将触发执行"error_log"表的插入操做 delimiter %% create trigger tri_after_insert_cmd after insert on cmd for each row begin if new.success="no" then # 若是即将插入的记录的"success"字段是"no",则执行下面的语句 insert error_log(error_cmd,error_time) value(new.cmd,new.sub_time); # 加分号 end if; end %% delimiter ; 🥝开始模拟插入记录 insert cmd(user,permi,cmd,sub_time,success) value ("shawn","0644","ls -l /root",now(),"yes"), ("shawn","0644","ps -elf",now(),"yes"), ("shawn","0644","groupadd xing",now(),"no"), ("shawn","0644","cat /etc/gshadow",now(),"no"); 🥝查看"error_log" select * from error_log;
drop trigger tri_after_insert_cmd
🍎开启事务 begin; # 或者下面的语句 start transaction; 🍎事务回滚(回滚到以前的状态,并关闭事务) rollback; # 回滚 + 关闭 🍎事务提交(将修改提交,并关闭事务) commit; # 提交 + 关闭
由上面关键字能够看出, 一个事务的开始对应一个回滚或者提交, 以后就须要从新开启事务linux
🍎先建立一个用户余额表并插入记录 create table user( id int primary key auto_increment, name varchar(16) not null, balance int not null ); insert user(name,balance) value ("shawn",150000), ("song",20000), ("xing",520022), ("hai",10000); select * from user; # 查看一下全部记录 🍎开启事务 begin; # 或者 start transaction; 🍎更新记录 update user set balance=100 where name="shawn"; update user set balance=100 where name="song"; update user set balance=100 where name="xing"; update user set balance=200 where name="hai"; select * from user; # 查看一下是否修改为功 🍎事务回滚 rollback; # 回滚以后, 该事务就关闭了 select * from user; # 查看一下是否回滚到原来的数据 🍎再开启一个事务 begin; 🍎再次对数据进行更新 update user set balance=200 where name="shawn"; update user set balance=200 where name="song"; commit; # 事务提交, 并关闭了该事务 select * from user; # 查看数据的变化 rollback; # 再次使用事务回滚将不在起做用, 由于事务已经关闭了 select * from user;
"应用程序" : 程序员本身写代码开发 "mysql" : 提早写好的存储过程, 提供给程序来调用 🔰优势 : 提高了开发效率, 执行效率提高(只传输'存储过程名') 🔰缺点 : 可扩展性查, 可能使用者的一些变更就须要修改整个存储过程
程序员在开发应用程序的过程当中涉及到的数据库操做也是本身手动编写 🔰优势 : 扩展性很高 🔰缺点 : 开发效率低, 编写SQL语句太过繁琐, 且有些重复, 后期维护也不方便
程序员开发程序时只写程序代码, 而sql语句是基于别人写好的框架直接拿过来使用 (例如使用ORM框架) 🔰优势 : 开发效率比第一种和第二种都要高 🔰缺点 : 语句的可扩展性差, 并可能出现效率低下的问题
delimiter %% # 更换默认结束符 create procedure [存储过程名]() begin [一堆SQL语句] end %% delimiter ; # 将默认结束符改回来
🍅先建立一个表, 在插入几条子记录 create table text( id int primary key auto_increment, name varchar(100) not null, sub_time datetime); insert text(name,sub_time) value ("python详解",now()), ("Java入门",now()), ("派大星的故事",now()), ("小江放牛羊",now()); 🍅建立无参存储过程,对"text"表进行一些操做 delimiter %% create procedure p01() begin select * from text; insert text(name,sub_time) value("杀牛羊手法2",now()); end %% delimiter ; 🔰在"mysql"中调用 call p01(); 🔰在"Python"中的"pymysql"中调用 # 首先导入模块并链接数据库 import pymysql conn = pymysql.connect( host="127.0.0.1", port=3306, user="root", password="123456", database="test03", charset="utf8" ) # 获得游标 cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.callproc("p01") # 调用存储过程 print(cursor.fetchall()) # 拿到结果并输出 cursor.close() # 关闭游标 conn.close() # 关闭链接
"in" : 仅用于传入参数 (声明后面的变量为外部参数) "out" : 仅用于返回值 (声明后面的变量是一个返回值,须要使用"set"声明) "inout" : 既能够传入时使用有能够返回值时使用 (声明后面的变量能够但参数也能够当返回值,须要"set"声明)
delimiter %%% # 修改默认结束符 create procedure [存储过程名]( in|out|inout [参数名] [类型], .....(能够多个参数), ...... ) begin [sql语句] end %%% delimiter ; # 将默认结束符改回来
🍅建立有参存储过程 delimiter %%% create procedure p02( in num01 int ) begin select * from text where id=num01; end %%% delimiter ; 🍅在"mysql"中直接调用 call p02(4); 🍅"Python"中使用"pymysql"模块调用 import pymysql conn = pymysql.connect( host="127.0.0.1", port=3306, user="root", password="123456", database="test03", charset="utf8" ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.callproc("p02",(4,)) # 参数传入的是一个元组 print(cursor.fetchall()) cursor.close() conn.close()
🍅建立有参存储过程 delimiter %%% create procedure p03( in num01 int, out res01 int ) begin select * from text where id=num01; set res01=num01+1; end %%% delimiter ; 🍅在"mysql"中调用 call p03(4,@res01); # @res01 表示定义一个全局变量来接收返回值 select @res01; # 查看这个返回值 🍅在"python"中使用"pymysql"调用 import pymysql conn = pymysql.connect( host="127.0.0.1", port=3306, user="root", password="123456", database="test03", charset="utf8" ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) res = "" cursor.callproc("p03", (4, res)) # 第二个参数是用来接收返回值的 print(cursor.fetchall()) cursor.execute("select @_p03_0,@_p03_1;") # "@_p03_0"表明的是传入的第一个参数,"@_p03_1"表明的是第二的参数,也就是返回值 print(cursor.fetchall()) cursor.close() conn.close()
🍅建立存储过程 delimiter %%% create procedure p04( inout num01 int ) begin select * from text where id>num01; set num01=num01+num01; end %%% delimiter ; 🍅在"mysql"中调用 set @res=2; # 先定义一个全局变量 call p04(@res); # 而后传进去,一方面当参数, 一方面接收返回值 select @res # 查看这个返回值 🍅在"Python"使用"pymysql"调用 import pymysql conn = pymysql.connect( host="127.0.0.1", port=3306, user="root", password="123456", database="test03", charset="utf8" ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) res = 2 # 定义一个变量 cursor.callproc("p04", (res,)) # 传入这个变量,可当参数,也可接收返回值 print(cursor.fetchall()) cursor.execute("select @_p04_0;") # 查看返回值 print(cursor.fetchall()) cursor.close() conn.close()
drop procedure [存储过程名];
drop procedure p01;
👉🏻mysql 内置函数官方文档👈🏻程序员
👉🏻mysql 内置函数中文文档👈🏻web
ROUND(x,y) # 返回参数x的四舍五入的有y位小数的值 RAND() # 返回 0 到1内的随机值,能够经过提供一个参数(种子)使RAND()随机数生成器生成一个指定的值
AVG(col) # 返回指定列的平均值 COUNT(col) # 返回指定列中非NULL值的个数 MIN(col) # 返回指定列的最小值 MAX(col) # 返回指定列的最大值 SUM(col) # 返回指定列的全部值之和 GROUP_CONCAT(col) # 返回由属于一组的列值链接组合而成的结果
CHAR_LENGTH(str) # 返回值为字符串str 的长度,长度的单位为字符,一个多字节字符算做一个单字符。 CONCAT(str1,str2,...) # 字符串拼接,若有任何一个参数为NULL,则返回值为 NULL CONCAT_WS(separator,str1,str2,...) # 字符串拼接(自定义链接符) CONCAT_WS() # 不会忽略任何空字符串 (然而会忽略全部的 NULL) CONV(N,from_base,to_base) # 进制转换 例如:SELECT CONV('a',16,2); 表示将 a 由16进制转换为2进制字符串表示 FORMAT(X,D) # 将数字X 的格式写为'#,###,###.##',以四舍五入的方式保留小数点后 D 位,并将结果以字符串的形式返回。若 D 为 0,则返回结果不带有小数点,或不含小数部分 例如:SELECT FORMAT(12332.1,4); 结果为: '12,332.1000' INSERT(str,pos,len,newstr) # 在str的指定位置插入字符串, pos:要替换位置其实位置, len:替换的长度, newstr:新字符串 特别的:若是pos超过原字符串长度,则返回原字符串;若是len超过原字符串长度,则由新字符串彻底替换 INSTR(str,substr) # 返回字符串 str 中子字符串的第一个出现位置 LEFT(str,len) # 返回字符串str 从开始的len位置的子序列字符 LOWER(str) # 变小写 UPPER(str) # 变大写 REVERSE(str) # 返回字符串 str ,顺序和字符顺序相反。 SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len) # 不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。倘若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在如下格式的函数中能够对pos 使用一个负值 mysql> SELECT SUBSTRING('Quadratically',5); -> 'ratically' mysql> SELECT SUBSTRING('foobarbar' FROM 4); -> 'barbar' mysql> SELECT SUBSTRING('Quadratically',5,6); -> 'ratica' mysql> SELECT SUBSTRING('Sakila', -3); -> 'ila' mysql> SELECT SUBSTRING('Sakila', -5, 3); -> 'aki' mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2); -> 'ki'
CURDATE()或CURRENT_DATE() # 返回当前的日期 CURTIME()或CURRENT_TIME() # 返回当前的时间 DAYOFWEEK(date) # 返回date所表明的一星期中的第几天(1~7) DAYOFMONTH(date) # 返回date是一个月的第几天(1~31) DAYOFYEAR(date) # 返回date是一年的第几天(1~366) DAYNAME(date) # 返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE); FROM_UNIXTIME(ts,fmt) # 根据指定的fmt格式,格式化UNIX时间戳ts HOUR(time) # 返回time的小时值(0~23) MINUTE(time) # 返回time的分钟值(0~59) MONTH(date) # 返回date的月份值(1~12) MONTHNAME(date) # 返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE); NOW() # 返回当前的日期和时间 QUARTER(date) # 返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE); WEEK(date) # 返回日期date为一年中第几周(0~53) YEAR(date) # 返回日期date的年份(1000~9999)
MD5() # 计算字符串str的MD5校验和 PASSWORD(str) # 返回字符串str的加密版本,这个加密过程是不可逆转的,和UNIX密码加密过程使用不一样的算法
CASE WHEN[test1] THEN [result1]...ELSE [default] END # 若是testN是真,则返回resultN,不然返回default CASE [test] WHEN[val1] THEN [result]...ELSE [default]END # 若是test和valN相等,则返回resultN,不然返回default IF(test,t,f) # 若是test是真,返回t;不然返回f IFNULL(arg1,arg2) # 若是arg1不是空,返回arg1,不然返回arg2 NULLIF(arg1,arg2) # 若是arg1=arg2返回NULL;不然返回arg1
ps : 流程控制练习算法
🍎准备表 : 将下面数据复制到"sql"后缀的文件中 /* Navicat MySQL Data Transfer Source Server : localhost_3306 Source Server Version : 50720 Source Host : localhost:3306 Source Database : student Target Server Type : MYSQL Target Server Version : 50720 File Encoding : 65001 Date: 2018-01-02 12:05:30 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for course -- ---------------------------- DROP TABLE IF EXISTS `course`; CREATE TABLE `course` ( `c_id` int(11) NOT NULL, `c_name` varchar(255) DEFAULT NULL, `t_id` int(11) DEFAULT NULL, PRIMARY KEY (`c_id`), KEY `t_id` (`t_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of course -- ---------------------------- INSERT INTO `course` VALUES ('1', 'python', '1'); INSERT INTO `course` VALUES ('2', 'java', '2'); INSERT INTO `course` VALUES ('3', 'linux', '3'); INSERT INTO `course` VALUES ('4', 'web', '2'); -- ---------------------------- -- Table structure for score -- ---------------------------- DROP TABLE IF EXISTS `score`; CREATE TABLE `score` ( `id` int(11) NOT NULL AUTO_INCREMENT, `s_id` int(10) DEFAULT NULL, `c_id` int(11) DEFAULT NULL, `num` double DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of score -- ---------------------------- INSERT INTO `score` VALUES ('1', '1', '1', '79'); INSERT INTO `score` VALUES ('2', '1', '2', '78'); INSERT INTO `score` VALUES ('3', '1', '3', '35'); INSERT INTO `score` VALUES ('4', '2', '2', '32'); INSERT INTO `score` VALUES ('5', '3', '1', '66'); INSERT INTO `score` VALUES ('6', '4', '2', '77'); INSERT INTO `score` VALUES ('7', '4', '1', '68'); INSERT INTO `score` VALUES ('8', '5', '1', '66'); INSERT INTO `score` VALUES ('9', '2', '1', '69'); INSERT INTO `score` VALUES ('10', '4', '4', '75'); INSERT INTO `score` VALUES ('11', '5', '4', '66.7'); -- ---------------------------- -- Table structure for student -- ---------------------------- DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `s_id` varchar(20) NOT NULL, `s_name` varchar(255) DEFAULT NULL, `s_age` int(10) DEFAULT NULL, `s_sex` char(1) DEFAULT NULL, PRIMARY KEY (`s_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of student -- ---------------------------- INSERT INTO `student` VALUES ('1', '鲁班', '12', '男'); INSERT INTO `student` VALUES ('2', '貂蝉', '20', '女'); INSERT INTO `student` VALUES ('3', '刘备', '35', '男'); INSERT INTO `student` VALUES ('4', '关羽', '34', '男'); INSERT INTO `student` VALUES ('5', '张飞', '33', '女'); -- ---------------------------- -- Table structure for teacher -- ---------------------------- DROP TABLE IF EXISTS `teacher`; CREATE TABLE `teacher` ( `t_id` int(10) NOT NULL, `t_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`t_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of teacher -- ---------------------------- INSERT INTO `teacher` VALUES ('1', '大王'); INSERT INTO `teacher` VALUES ('2', 'alex'); INSERT INTO `teacher` VALUES ('3', 'egon'); INSERT INTO `teacher` VALUES ('4', 'peiqi');
🍎建立一个库,并导入该文件 create database school_test; # 建立一个库 use school_test source J:\MySql\mysql-5.6.48-winx64\data\sql_file\school_test.sql # 导入该文件(须要文件路徑) show tables; # 查看是否导入成功 select * from student; select * from teacher;
🍎统计各科各分数段人数, 显示格式:课程ID,课程名称,[100-85],[85-70],[70-60],[ <60] # 以各学科分组,显示课程ID和课程名字,因而须要将course与score链表,使用流程控制+sum()函数统计各分数段的人数 select course.c_id,course.c_name, sum(case when (num between 85 and 100) then 1 else 0 end) as "[100-85]", sum(case when (num between 70 and 84) then 1 else 0 end) as "[85-70]", sum(case when (num between 60 and 69) then 1 else 0 end) as "[70-60]", sum(case when num<60 then 1 else 0 end) as "[ <60]" from score,course where score.c_id=course.c_id group by score.c_id;
select date_format([date],[format]) # 将传入的时间(date)按照传入的格式(format)进行转换
select date_format("2021-02-22","%W %M %Y") as time; # 星期 月 年 select date_format("2020-01-25 11:14:23","%H:%i:%s") as time; # 时 分 秒 select date_format("2020-01-25 11:14:23","%D %y %d %m %b %j") as time; # 日 年 日 月 月 日 select date_format("1111-11-11 11:11:11","%H %k %I %r %T %S %w")as time;
🍅将"text"表中的"sub_time"提取出来转换成"时分秒"格式进行分组,并统计个数 select * from text; select date_format(sub_time,"%H:%i:%s") as time,count(id) from text group by time;
自定义函数不一样于存储过程, 函数中不能写 sql 语句(不然报错), 函数仅仅是 sql 中被应用的功能; 若是须要在 begin...end 中放置 sql 语句, 使用存储过程就好了sql
delimiter %%% create function [函数名]( [参数1] [类型], [参数2] [类型]) returns [类型] begin [一系列代码] end %%% delimiter ;
🍅定义一个函数(求两个数和) delimiter %%% # 修改默认结束符 create function f01( num01 int, num02 int) # 定义参数以及类型 returns int # 设置返回值的类型为 int begin declare num03 int; # 声明变量 num03 为 int 类型 set num03=num01+num02; return(num03); end %%% delimiter ; # 将默认结束符修改回来 🍅调用自定义函数 select f01(2,4); # 查询+调用 select f01(2,4) into @res; # 调用并将返回值给变量 @res select @res; # 查看变量值
🍅定义一个函数 delimiter %%% create function f012( num01 int) returns int begin declare res int default 0; # 声明变量 res 为 int 类型,若是传入的不是 int,默认返回 0 if num01 = 10 then set res = num01*num01; elseif num01 = 20 then set res = num01*num01; elseif num01 = 30 then set res = num01*num01; else set res = num01; end if; return(res); end %%% delimiter ; 🍅调用 select f012(10); select f012(20); select f012(30); select f012(40); select f012("ad");
drop function [函数名]; drop function f012;
delimiter %%% create procedure p01(in num int) begin if num = 1 then select 1; elseif num = 2 then select 2; else select 3; end if; end %%% delimiter ;
delimiter %%% create procedure p02() begin declare num int; set num = 0; while num < 3 do select num; set num = num + 1; end while; end %%% delimiter ;
delimiter %%% create procedure p03() begin declare num int; set num = 0; repeat select num; set num = num + 1; until num > 3 # 结束条件:当num>3时结束 end repeat; end %%% delimiter ;
delimiter %%% create procedure p04() begin declare num int default 0; myloop:loop set num=num+1; if num>=3 then leave myloop; # 当 num>=3 结束循环 end if; select num; end loop myloop; end %%% delimiter ;
---end---数据库