語法 : 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---數據庫