数据库---mysql内置功能
一、視圖
簡介:
視圖是一個虛擬表(非真實存在),其本質是【根據SQL語句獲取動態的數據集,并為其命名】,用戶使用時只需使用【名稱】即可獲取結果集,可以將該結果集當做表來使用。使用視圖我們可以把查詢過程中的臨時表摘出來,用視圖去實現,這樣以后再想操作該臨時表的數據時就無需重寫復雜的sql了,直接去視圖中查找即可,但視圖有明顯地效率問題,并且視圖是存放在數據庫中的,如果我們程序中使用的sql過分依賴數據庫中的視圖,即強耦合,那就意味著擴展sql極為不便,因此并不推薦使用。
使用方法:
#兩張有關系的表 mysql> select * from course; +-----+--------+------------+ | cid | cname | teacher_id | +-----+--------+------------+ | 1 | 生物 | 1 | | 2 | 物理 | 2 | | 3 | 體育 | 3 | | 4 | 美術 | 2 | +-----+--------+------------+ rows in set (0.00 sec)mysql> select * from teacher; +-----+-----------------+ | tid | tname | +-----+-----------------+ | 1 | 張磊老師 | | 2 | 李平老師 | | 3 | 劉海燕老師 | | 4 | 朱云海老師 | | 5 | 李杰老師 | +-----+-----------------+ rows in set (0.00 sec)#查詢李平老師教授的課程名 mysql> select cname from course where teacher_id = (select tid from teacher where tname='李平老師'); +--------+ | cname | +--------+ | 物理 | | 美術 | +--------+ rows in set (0.00 sec)#子查詢出臨時表,作為teacher_id等判斷依據 select tid from teacher where tname='李平老師'臨時表應用舉例 視圖的使用方法1.創建視圖
#語法:CREATE VIEW 視圖名稱 AS SQL語句 create view teacher_view as select tid from teacher where tname='李平老師';#于是查詢李平老師教授的課程名的sql可以改寫為 mysql> select cname from course where teacher_id = (select tid from teacher_view); +--------+ | cname | +--------+ | 物理 | | 美術 | +--------+ rows in set (0.00 sec)#!!!注意注意注意: #1. 使用視圖以后就無需每次都重寫子查詢的sql,但是這么效率并不高,還不如我們寫子查詢的效率高#2. 而且有一個致命的問題:視圖是存放到數據庫里的,如果我們程序中的sql過分依賴于數據庫中存放的視圖, 那么意味著,一旦sql需要修改且涉及到視圖的部分,則必須去數據庫中進行修改,而通常在公司中數據庫有專門的DBA負責, 你要想完成修改,必須付出大量的溝通成本DBA可能才會幫你完成修改,極其地不方便 創建視圖2.使用視圖
#修改視圖,原始表也跟著改 mysql> select * from course; +-----+--------+------------+ | cid | cname | teacher_id | +-----+--------+------------+ | 1 | 生物 | 1 | | 2 | 物理 | 2 | | 3 | 體育 | 3 | | 4 | 美術 | 2 | +-----+--------+------------+ rows in set (0.00 sec)mysql> create view course_view as select * from course; #創建表course的視圖 Query OK, 0 rows affected (0.52 sec)mysql> select * from course_view; +-----+--------+------------+ | cid | cname | teacher_id | +-----+--------+------------+ | 1 | 生物 | 1 | | 2 | 物理 | 2 | | 3 | 體育 | 3 | | 4 | 美術 | 2 | +-----+--------+------------+ rows in set (0.00 sec)mysql> update course_view set cname='xxx'; #更新視圖中的數據 Query OK, 4 rows affected (0.04 sec) Rows matched: 4 Changed: 4 Warnings: 0mysql> insert into course_view values(5,'yyy',2); #往視圖中插入數據 Query OK, 1 row affected (0.03 sec)mysql> select * from course; #發現原始表的記錄也跟著修改了 +-----+-------+------------+ | cid | cname | teacher_id | +-----+-------+------------+ | 1 | xxx | 1 | | 2 | xxx | 2 | | 3 | xxx | 3 | | 4 | xxx | 2 | | 5 | yyy | 2 | +-----+-------+------------+ rows in set (0.00 sec) 使用視圖?注意:我們不應該修改視圖中的記錄,而且在涉及多個表的情況下是根本無法修改視圖中的記錄的,如下圖
3.修改視圖
#語法:ALTER VIEW 視圖名稱 AS SQL語句mysql> alter view teacher_view as select * from course where cid>3;Query OK, 0 rows affected (0.04 sec)mysql> select * from teacher_view;+-----+-------+------------+| cid | cname | teacher_id |+-----+-------+------------+| 4 | xxx | 2 || 5 | yyy | 2 |+-----+-------+------------+rows in set (0.00 sec) 修改視圖4.刪除視圖
語法:DROP VIEW 視圖名稱DROP VIEW teacher_view 刪除視圖二、觸發器
簡介
使用觸發器可以定制用戶對表進行【增、刪、改】操作時前后的行為,注意:沒有查詢。這是mysql內部實現得觸發器得功能;
1.創建觸發器
# 插入前 CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW BEGIN... END# 插入后 CREATE TRIGGER 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 (id INT PRIMARY KEY auto_increment,USER CHAR (32),priv CHAR (10),cmd CHAR (64),sub_time datetime, #提交時間success enum ('yes', 'no') #0代表執行失敗 );CREATE TABLE errlog (id INT PRIMARY KEY auto_increment,err_cmd CHAR (64),err_time datetime );#創建觸發器 delimiter // CREATE TRIGGER tri_after_insert_cmd AFTER INSERT ON cmd FOR EACH ROW BEGINIF NEW.success = 'no' THEN #等值判斷只有一個等號INSERT INTO errlog(err_cmd, err_time) VALUES(NEW.cmd, NEW.sub_time) ; #必須加分號END IF ; #必須加分號 END// delimiter ;#往表cmd中插入記錄,觸發觸發器,根據IF的條件決定是否插入錯誤日志 INSERT INTO cmd (USER,priv,cmd,sub_time,success ) 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; +----+-----------------+---------------------+ | id | err_cmd | err_time | +----+-----------------+---------------------+ | 1 | cat /etc/passwd | 2017-09-14 22:18:48 | | 2 | useradd xxx | 2017-09-14 22:18:48 | +----+-----------------+---------------------+ rows in set (0.00 sec)插入后觸發觸發器 創建觸發器2.使用觸發器
觸發器無法由用戶直接調用,而知由于對表的【增/刪/改】操作被動引發的。 查看觸發器:show triggers\G;3.刪除觸發器
drop trigger tri_after_insert_cmd;三、儲存過程
1.儲存過程介紹
存儲過程包含了一系列可執行的sql語句,存儲過程存放于MySQL中,通過調用它的名字可以執行其內部的一堆sql
優點:
- 用于替代程序寫的SQL語句,實現程序與sql解耦
- 基于網絡傳輸,傳別名的數據量小,而直接傳sql數據量大
缺點:
- 程序員擴展不方便
補充
#方式一:MySQL:存儲過程程序:調用存儲過程#方式二:MySQL:程序:純SQL語句#方式三:MySQL:程序:類和對象,即ORM(本質還是純SQL語句)2.創建簡單的存儲過程(無參)
create table blog(id int primary key auto_increment,name varchar(16),sub_time datetime ); insert into blog(name,sub_time) values('alice',now()); delimiter // create procedure p1() beginselect * from blog;insert into blog(name,sub_time) values('xxx',now()); end // delimiter ;#在mysql中調用 call p1(); #在python中基于pymysql調用cursor.callproc('p1') print(cursor.fetchall())conn.commit() # 一定要有,否則在增刪改時,不能更新到數據庫; 示例代碼3.創建簡單的儲存過程(有參)
對于存儲過程,可以接收參數,其參數有三類:
- in 僅用于傳入參數用
- out 僅用于返回值用
- inout 既可以傳入又可以當作返回值?
4.執行儲存過程
-- 無參數call proc_name()-- 有參數,全incall proc_name(1,2)-- 有參數,有in,out,inoutset @t1=0;set @t2=3;call proc_name(1,2,@t1,@t2)2.在python中基于pymysql執行存儲過程#!/usr/bin/env python# -*- coding:utf-8 -*-import pymysqlconn = 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) 示例代碼5.刪除儲存過程
drop procedure proc_name;?
四、事物
簡介
事務用于將某些操作的多個SQL作為原子性操作,一旦有某一個出現錯誤,即可回滾到原來的狀態,從而保證數據庫數據完整性。
一堆sql語句:要么同時執行成功,要么同時失敗 原子性
場景: 轉賬;
介紹:
delimiter // create procedure p4(out status int)BEGIN1. 聲明如果出現異常則執行{set status = 1;rollback;}開始事務-- 由秦兵賬戶減去100-- 方少偉賬戶加90-- 張根賬戶加10commit;結束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())事務 實現五、函數
參考:https://www.luffycity.com/python-book/di-8-zhang-mysql-shu-ju-ku/87-mysqlnei-zhi-gong-neng/875-han-shu.html
?
?
? ?
轉載于:https://www.cnblogs.com/Mryang123/p/9039533.html
總結
以上是生活随笔為你收集整理的数据库---mysql内置功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces 833B 题解(D
- 下一篇: mysql之distinct