視圖,觸發器,事物,儲存過程,函數,流程控制
阿新 • • 發佈:2017-09-18
tro then database lap data rtrim( -s sun .com
一視圖 建表
create database o; use o; create table teacher( tid int primary key auto_increment, tname char(32) ); insert into teacher(tname) values (‘張磊老師‘),(‘李平老師‘),(‘劉海燕老師‘),(‘朱雲海老師‘),(‘李傑老師‘); create table course( cid int primary key auto_increment, cname char(32), teacher_id int ); insert into course(cname,teacher_id) values (‘生物‘,1),(‘物理‘,2),(‘體育‘,3),(‘美術‘,2);
查詢
#查詢李平老師教授的課程名 select cname from course where teacher_id=(select tid from teacher where tname = ‘李平老師‘); #子查詢出臨時表,作為teacher_id等判斷依據 select tid from teacher where tname=‘李平老師‘
創建視圖,使用視圖,修改,刪除視圖
創建course視圖 create view course_view as select * from course; 更新視圖中的數據 update course_view set cname=‘xxxxx‘; 向視圖中插入數據 insert into course_view values(5,‘yyy‘,2); 原始數據跟著修改 select * from course; 修改視圖 alter view teacher_view as select * from course where cid>3; 刪除視圖 drop view teacher_view;
觸發器 ------創建觸發器
插入前 create taigger tri_before_insert_tb1 before insert on tb1 for each row begin ...... end 插入後 creste trgger tri_after_insert_tb1 after insert on tb1 for each row begin ...... end # 刪除前 CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW BEGIN ... END # 刪除後 CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW BEGIN ... END # 更新前 CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW BEGIN ... END # 更新後 CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW BEGIN ... END
準備表
create table cmd_log( id int primary key auto_increment, user_name char(32), priv char(10), cmd_log char(64), sub_time datetime,#提交時間
succcess enum(‘yes‘,‘no‘) );
create table err_log( id int primary key auto_increment, err_cmd char(64(, err_time datetime );
#創建觸發器
delimiter //
create trigger tri_after_insert_cmd_log after insert on cmd_log for each row begin if enw.succcess=
‘no‘ then insert into err_log(err_cmd,err_time) values(new.cmd,new.sub_time); end if; end // delimiter;
insert into cmd_log(user_name,priv,cmd_log,sub_time,succcess) values (‘egon‘,‘0755‘,‘ls -l /etc‘,NOW(),‘yes‘),
(‘egon‘,‘0755‘,‘cat /etc/passwd‘,NOW(),‘no‘), (‘egon‘,‘0755‘,‘useradd xxx‘,NOW(),‘no‘),
(‘egon‘,‘0755‘,‘ps aux‘,NOW(),‘yes‘);
#查詢錯誤日誌,發現有兩條
mysql> select * from errlog;
刪除觸發器
drop trigger tri_after_insert_cmd;
事物
事物 create table user( id int primary key auto_increment, name char(32), balance int ); insert into user(name,balance) values (‘花花‘,100); (‘狗剩‘,100); (‘二蛋‘,100); start transaction; update user set balance=50 where name=‘花花‘; update user set balance=110 where name=‘二蛋‘; update user set balance=140 where name=‘狗剩‘; rollback; commit;
存儲過程
存儲過程的優點:
1. 用於替代程序寫的SQL語句,實現程序與sql解耦 2. 基於網絡傳輸,傳別名的數據量小,而直接傳sql數據量大
存儲過程的缺點:
1 執行效率低 2. 程序員擴展功能不方便
補充:程序與數據庫結合使用的三種方式
方式一:
MySQL:存儲過程 程序:調用存儲過程 方式二: MySQL: 程序:純SQL語句 方式三: MySQL: 程序:類和對象,即ORM(本質還是純SQL語句)
二 創建簡單存儲過程(無參)
delimiter // create procedure p1() BEGIN select * from blog; INSERT into blog(name,sub_time) values("xxx",now()); END // delimiter ; #在mysql中調用 call p1() #在python中基於pymysql調用 cursor.callproc(‘p1‘) print(cursor.fetchall())View Code
三 創建存儲過程(有參)
對於存儲過程,可以接收參數,其參數有三類: in 僅用於傳入參數用 out 僅用於返回值用 inout 既可以傳入又可以當作返回值
delimiter // create procedure p2( in n1 int, in n2 int ) BEGIN select * from blog where id > n1; END // delimiter ; #在mysql中調用 call p2(3,2) #在python中基於pymysql調用 cursor.callproc(‘p2‘,(3,2)) print(cursor.fetchall())in:傳入參數
delimiter // create procedure p3( in n1 int, out res int ) BEGIN select * from blog where id > n1; set res = 1; END // delimiter ; #在mysql中調用 set @res=0; #0代表假(執行失敗),1代表真(執行成功) call p3(3,@res); select @res; #在python中基於pymysql調用 cursor.callproc(‘p3‘,(3,0)) #0相當於set @res=0 print(cursor.fetchall()) #查詢select的查詢結果 cursor.execute(‘select @_p3_0,@_p3_1;‘) #@p3_0代表第一個參數,@p3_1代表第二個參數,即返回值 print(cursor.fetchall())out:返回值
delimiter // create procedure p4( inout n1 int ) BEGIN select * from blog where id > n1; set n1 = 1; END // delimiter ; #在mysql中調用 set @x=3; call p4(@x); select @x; #在python中基於pymysql調用 cursor.callproc(‘p4‘,(3,)) print(cursor.fetchall()) #查詢select的查詢結果 cursor.execute(‘select @_p4_0;‘) print(cursor.fetchall())inout:既可以傳入又可以返回
#介紹 delimiter // create procedure p4( out status int ) BEGIN 1. 聲明如果出現異常則執行{ set status = 1; rollback; } 開始事務 -- 由秦兵賬戶減去100 -- 方少偉賬戶加90 -- 張根賬戶加10 commit; 結束 set status = 2; END // delimiter ; #實現 delimiter // create PROCEDURE p5( OUT p_return_code tinyint ) BEGIN DECLARE exit handler for sqlexception BEGIN -- ERROR set p_return_code = 1; rollback; END; DECLARE exit handler for sqlwarning BEGIN -- WARNING set p_return_code = 2; rollback; END; START TRANSACTION; DELETE from tb1; #執行失敗 insert into blog(name,sub_time) values(‘yyy‘,now()); COMMIT; -- SUCCESS set p_return_code = 0; #0代表執行成功 END // delimiter ; #在mysql中調用存儲過程 set @res=123; call p5(@res); select @res; #在python中基於pymysql調用存儲過程 cursor.callproc(‘p5‘,(123,)) print(cursor.fetchall()) #查詢select的查詢結果 cursor.execute(‘select @_p5_0;‘) print(cursor.fetchall())事務
執行存儲過程
-- 無參數 call proc_name() -- 有參數,全in call proc_name(1,2) -- 有參數,有in,out,inout set @t1=0; set @t2=3; call proc_name(1,2,@t1,@t2) 執行存儲過程在MySQL中執行存儲過程
#!/usr/bin/env python # -*- coding:utf-8 -*- import pymysql conn = pymysql.connect(host=‘127.0.0.1‘, port=3306, user=‘root‘, passwd=‘123‘, db=‘t1‘) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 執行存儲過程 cursor.callproc(‘p1‘, args=(1, 22, 3, 4)) # 獲取執行完存儲的參數 cursor.execute("select @_p1_0,@_p1_1,@_p1_2,@_p1_3") result = cursor.fetchall() conn.commit() cursor.close() conn.close() print(result)在python中基於pymysql執行存儲過程
刪除存儲過程
drop procedure proc_name;
函數
CHAR_LENGTH(str) 返回值為字符串str 的長度,長度的單位為字符。一個多字節字符算作一個單字符。 對於一個包含五個二字節字符集, LENGTH()返回值為 10, 而CHAR_LENGTH()的返回值為5。 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) 變大寫 LTRIM(str) 返回字符串 str ,其引導空格字符被刪除。 RTRIM(str) 返回字符串 str ,結尾空格字符被刪去。 SUBSTRING(str,pos,len) 獲取字符串子序列 LOCATE(substr,str,pos) 獲取子序列索引位置 REPEAT(str,count) 返回一個由重復的字符串str 組成的字符串,字符串str的數目等於count 。 若 count <= 0,則返回一個空字符串。 若str 或 count 為 NULL,則返回 NULL 。 REPLACE(str,from_str,to_str) 返回字符串str 以及所有被字符串to_str替代的字符串from_str 。 REVERSE(str) 返回字符串 str ,順序和字符順序相反。 RIGHT(str,len) 從字符串str 開始,返回從後邊開始len個字符組成的子序列 SPACE(N) 返回一個由N空格組成的字符串。 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‘ TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str) TRIM(remstr FROM] str) 返回字符串 str , 其中所有remstr 前綴和/或後綴都已被刪除。若分類符BOTH、LEADIN或TRAILING中沒有一個是給定的,則假設為BOTH 。 remstr 為可選項,在未指定情況下,可刪除空格。 mysql> SELECT TRIM(‘ bar ‘); -> ‘bar‘ mysql> SELECT TRIM(LEADING ‘x‘ FROM ‘xxxbarxxx‘); -> ‘barxxx‘ mysql> SELECT TRIM(BOTH ‘x‘ FROM ‘xxxbarxxx‘); -> ‘bar‘ mysql> SELECT TRIM(TRAILING ‘xyz‘ FROM ‘barxxyz‘); -> ‘barx‘部分內置函數
#1 基本使用 mysql> SELECT DATE_FORMAT(‘2009-10-04 22:23:00‘, ‘%W %M %Y‘); -> ‘Sunday October 2009‘ mysql> SELECT DATE_FORMAT(‘2007-10-04 22:23:00‘, ‘%H:%i:%s‘); -> ‘22:23:00‘ mysql> SELECT DATE_FORMAT(‘1900-10-04 22:23:00‘, -> ‘%D %y %a %d %m %b %j‘); -> ‘4th 00 Thu 04 10 Oct 277‘ mysql> SELECT DATE_FORMAT(‘1997-10-04 22:23:00‘, -> ‘%H %k %I %r %T %S %w‘); -> ‘22 22 10 10:23:00 PM 22:23:00 00 6‘ mysql> SELECT DATE_FORMAT(‘1999-01-01‘, ‘%X %V‘); -> ‘1998 52‘ mysql> SELECT DATE_FORMAT(‘2006-06-00‘, ‘%d‘); -> ‘00‘ #2 準備表和記錄 CREATE TABLE blog ( id INT PRIMARY KEY auto_increment, NAME CHAR (32), sub_time datetime ); INSERT INTO blog (NAME, sub_time) VALUES (‘第1篇‘,‘2015-03-01 11:31:21‘), (‘第2篇‘,‘2015-03-11 16:31:21‘), (‘第3篇‘,‘2016-07-01 10:21:31‘), (‘第4篇‘,‘2016-07-22 09:23:21‘), (‘第5篇‘,‘2016-07-23 10:11:11‘), (‘第6篇‘,‘2016-07-25 11:21:31‘), (‘第7篇‘,‘2017-03-01 15:33:21‘), (‘第8篇‘,‘2017-03-01 17:32:21‘), (‘第9篇‘,‘2017-03-01 18:31:21‘); #3. 提取sub_time字段的值,按照格式後的結果即"年月"來分組 SELECT DATE_FORMAT(sub_time,‘%Y-%m‘),COUNT(1) FROM blog GROUP BY DATE_FORMAT(sub_time,‘%Y-%m‘); #結果 +-------------------------------+----------+ | DATE_FORMAT(sub_time,‘%Y-%m‘) | COUNT(1) | +-------------------------------+----------+ | 2015-03 | 2 | | 2016-07 | 4 | | 2017-03 | 3 | +-------------------------------+----------+ rows in set (0.00 sec)需要掌握函數:date_format
delimiter // create function f1( i1 int, i2 int) returns int BEGIN declare num int; set num = i1 + i2; return(num); END // delimiter ;View Code
delimiter // create function f5( i int ) returns int begin declare res int default 0; if i = 10 then set res=100; elseif i = 20 then set res=200; elseif i = 30 then set res=300; else set res=400; end if; return res; end // delimiter ;View Code
刪除函數
drop function func_name;
執行函數
# 獲取返回值 select UPPER(‘egon‘) into @res; SELECT @res; # 在查詢中使用 select f1(11,nid) ,name from tb2
流程控制
條件語句
delimiter // CREATE PROCEDURE proc_if () BEGIN declare i int default 0; if i = 1 THEN SELECT 1; ELSEIF i = 2 THEN SELECT 2; ELSE SELECT 7; END IF; END // delimiter ; if條件語句View Code
循環語句
delimiter // CREATE PROCEDURE proc_while () BEGIN DECLARE num INT ; SET num = 0 ; WHILE num < 10 DO SELECT num ; SET num = num + 1 ; END WHILE ; END // delimiter ; while循環
delimiter // CREATE PROCEDURE proc_repeat () BEGIN DECLARE i INT ; SET i = 0 ; repeat select i; set i = i + 1; until i >= 5 end repeat; END // delimiter ; repeat循環
BEGIN declare i int default 0; loop_label: loop set i=i+1; if i<8 then iterate loop_label; end if; if i>=10 then leave loop_label; end if; select i; end loop loop_label; END loop
視圖,觸發器,事物,儲存過程,函數,流程控制