1、視圖 html
數據庫視圖是虛擬表或邏輯表,它被定義爲具備鏈接的SQL SELECT查詢語句。其本質是爲經常使用的查詢語句起個別名。用戶使用時只需使用【名稱】便可獲取結果集,並能夠將其看成表來使用。不是真正存在。視圖存在數據庫中。python
數據庫視圖是動態的,由於它與物理模式無關。數據庫系統將數據庫視圖存儲爲具備鏈接的SQL SELECT語句。當表的數據發生變化時,視圖也反映了這些數據的變化。mysql
數據庫視圖的優勢 算法
總而言之,使用視圖的大部分狀況是爲了保障數據安全性,提升查詢效率。sql
除了上面的優勢,使用數據庫視圖有幾個缺點:數據庫
1、建立視圖編程
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
1 參數解釋 2 1)OR REPLACE:表示替換已有視圖 3 2)ALGORITHM:表示視圖選擇算法,默認算法是UNDEFINED(未定義的):MySQL自動選擇要使用的算法 ;merge合併;temptable臨時表 4 3)select_statement:表示select語句 5 4)[WITH [CASCADED | LOCAL] CHECK OPTION]:表示視圖在更新時保證在視圖的權限範圍以內 6 cascade是默認值,表示更新視圖的時候,要知足視圖和表的相關條件 7 local表示更新視圖的時候,要知足該視圖定義的一個條件便可 8 TIPS:推薦使用WHIT [CASCADED|LOCAL] CHECK OPTION選項,能夠保證數據的安全性
基本格式: flask
create view <視圖名稱>[(column_list)]
as
select語句
with check option;
mysql> create view v_F_players(編號,名字,性別,電話) -> as -> select PLAYERNO,NAME,SEX,PHONENO from PLAYERS -> where SEX='F' -> with check option; Query OK, 0 rows affected (0.00 sec) mysql> desc v_F_players; +--------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+----------+------+-----+---------+-------+ | 編號 | int(11) | NO | | NULL | | | 名字 | char(15) | NO | | NULL | | | 性別 | char(1) | NO | | NULL | | | 電話 | char(13) | YES | | NULL | | +--------+----------+------+-----+---------+-------+ 4 rows in set (0.00 sec) mysql> select * from v_F_players; +--------+-----------+--------+------------+ | 編號 | 名字 | 性別 | 電話 | +--------+-----------+--------+------------+ | 8 | Newcastle | F | 070-458458 | | 27 | Collins | F | 079-234857 | | 28 | Collins | F | 010-659599 | | 104 | Moorman | F | 079-987571 | | 112 | Bailey | F | 010-548745 | +--------+-----------+--------+------------+ 5 rows in set (0.02 sec)
mysql> create view v_match -> as -> select a.PLAYERNO,a.NAME,MATCHNO,WON,LOST,c.TEAMNO,c.DIVISION -> from -> PLAYERS a,MATCHES b,TEAMS c -> where a.PLAYERNO=b.PLAYERNO and b.TEAMNO=c.TEAMNO; Query OK, 0 rows affected (0.03 sec) mysql> select * from v_match; +----------+-----------+---------+-----+------+--------+----------+ | PLAYERNO | NAME | MATCHNO | WON | LOST | TEAMNO | DIVISION | +----------+-----------+---------+-----+------+--------+----------+ | 6 | Parmenter | 1 | 3 | 1 | 1 | first | | 44 | Baker | 4 | 3 | 2 | 1 | first | | 83 | Hope | 5 | 0 | 3 | 1 | first | | 112 | Bailey | 12 | 1 | 3 | 2 | second | | 8 | Newcastle | 13 | 0 | 3 | 2 | second | +----------+-----------+---------+-----+------+--------+----------+ 5 rows in set (0.04 sec)
注意:顯示指定視圖列名,要求視圖名後面的列的數量必須匹配select子句中的列的數量。安全
2、查看視圖服務器
一、使用show create view語句查看視圖信息
1 mysql> show create view v_F_players\G; 2 *************************** 1. row *************************** 3 View: v_F_players 4 Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_F_players` AS select `PLAYERS`.`PLAYERNO` AS `編號`,`PLAYERS`.`NAME` AS `名字`,`PLAYERS`.`SEX` AS `性別`,`PLAYERS`.`PHONENO` AS `電話` from `PLAYERS` where (`PLAYERS`.`SEX` = 'F') WITH CASCADED CHECK OPTION 5 character_set_client: utf8 6 collation_connection: utf8_general_ci 7 1 row in set (0.00 sec)
二、視圖一旦建立完畢,就能夠像一個普通表那樣使用,視圖主要用來查詢
mysql> select * from view_name;
三、有關視圖的信息記錄在information_schema數據庫中的views表中
1 mysql> select * from information_schema.views 2 -> where TABLE_NAME='v_F_players'\G; 3 *************************** 1. row *************************** 4 TABLE_CATALOG: def 5 TABLE_SCHEMA: TENNIS 6 TABLE_NAME: v_F_players 7 VIEW_DEFINITION: select `TENNIS`.`PLAYERS`.`PLAYERNO` AS `編號`,`TENNIS`.`PLAYERS`.`NAME` AS `名字`,`TENNIS`.`PLAYERS`.`SEX` AS `性別`,`TENNIS`.`PLAYERS`.`PHONENO` AS `電話` from `TENNIS`.`PLAYERS` where (`TENNIS`.`PLAYERS`.`SEX` = 'F') 8 CHECK_OPTION: CASCADED 9 IS_UPDATABLE: YES 10 DEFINER: root@localhost 11 SECURITY_TYPE: DEFINER 12 CHARACTER_SET_CLIENT: utf8 13 COLLATION_CONNECTION: utf8_general_ci 14 1 row in set (0.00 sec)
3、視圖的更改
一、CREATE OR REPLACE VIEW語句修改視圖
基本格式:
create or replace view view_name as select語句;
在視圖存在的狀況下可對視圖進行修改,視圖不在的狀況下可建立視圖
二、ALTER語句修改視圖
ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] [DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER }] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]
注意:修改視圖是指修改數據庫中已存在的表的定義,當基表的某些字段發生改變時,能夠經過修改視圖來保持視圖和基本表之間一致
三、DML操做更新視圖
由於視圖自己沒有數據,所以對視圖進行的dml操做最終都體如今基表中
固然,視圖的DML操做,不是全部的視圖均可以作DML操做。
①select子句中包含distinct
②select子句中包含組函數
③select語句中包含group by子句
④select語句中包含order by子句
⑤select語句中包含union 、union all等集合運算符
⑥where子句中包含相關子查詢
⑦from子句中包含多個表
⑧若是視圖中有計算列,則不能更新
⑨若是基表中有某個具備非空約束的列未出如今視圖定義中,則不能作insert操做
四、drop刪除視圖
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
mysql> drop view v_student;
4、使用WITH CHECK OPTION約束
對於能夠執行DML操做的視圖,定義時能夠帶上WITH CHECK OPTION約束
做用:
對視圖所作的DML操做的結果,不能違反視圖的WHERE條件的限制。
示例:建立視圖,包含1960年以前出生的全部球員(老兵)
mysql> create view v_veterans -> as -> select * from PLAYERS -> where birth_date < '1960-01-01' -> with check option; Query OK, 0 rows affected (0.01 sec) mysql> select * from v_veterans; +----------+---------+----------+------------+-----+--------+----------------+---------+----------+-----------+------------+----------+ | PLAYERNO | NAME | INITIALS | BIRTH_DATE | SEX | JOINED | STREET | HOUSENO | POSTCODE | TOWN | PHONENO | LEAGUENO | +----------+---------+----------+------------+-----+--------+----------------+---------+----------+-----------+------------+----------+ | 2 | Everett | R | 1948-09-01 | M | 1975 | Stoney Road | 43 | 3575NH | Stratford | 070-237893 | 2411 | | 39 | Bishop | D | 1956-10-29 | M | 1980 | Eaton Square | 78 | 9629CD | Stratford | 070-393435 | NULL | | 83 | Hope | PK | 1956-11-11 | M | 1982 | Magdalene Road | 16A | 1812UP | Stratford | 070-353548 | 1608 | +----------+---------+----------+------------+-----+--------+----------------+---------+----------+-----------+------------+----------+ 3 rows in set (0.02 sec)
mysql> update v_veterans -> set BIRTH_DATE='1970-09-01' -> where PLAYERNO=39; ERROR 1369 (HY000): CHECK OPTION failed 'TENNIS.v_veterans'
嵌套視圖:定義在另外一個視圖的上面的視圖
mysql> create view v_ear_veterans -> as -> select * from v_veterans -> where JOINED < 1980;
使用WITH CHECK OPTION約束時,(不指定選項則默認是CASCADED)
可使用CASCADED或者 LOCAL選項指定檢查的程度:
WITH CASCADED CHECK OPTION:檢查全部的視圖
例如:嵌套視圖及其底層的視圖
WITH LOCAL CHECK OPTION:只檢查將要更新的視圖自己
例如:對嵌套視圖不檢查其底層的視圖
5、定義視圖時的其餘選項
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] [DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER }] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]
1、ALGORITHM選項:選擇在處理定義視圖的select語句中使用的方法 ①UNDEFINED:MySQL將自動選擇所要使用的算法 ②MERGE:將視圖的語句與視圖定義合併起來,使得視圖定義的某一部分取代語句的對應部分 ③TEMPTABLE:將視圖的結果存入臨時表,而後使用臨時表執行語句 缺省ALGORITHM選項等同於ALGORITHM = UNDEFINED 2、DEFINER選項:指出誰是視圖的建立者或定義者 ①definer= '用戶名'@'登陸主機' ②若是不指定該選項,則建立視圖的用戶就是定義者,指定關鍵字CURRENT_USER(當前用戶)和不指定該選項效果相同 3、SQL SECURITY選項:要查詢一個視圖,首先必需要具備對視圖的select權限。 可是,若是同一個用戶對於視圖所訪問的表沒有select權限,那會怎麼樣? SQL SECURITY選項決定執行的結果: ①SQL SECURITY DEFINER:定義(建立)視圖的用戶必須對視圖所訪問的表具備select權限,也就是說未來其餘用戶訪問表的時候以定義者的身份,此時其餘用戶並無訪問權限。 ②SQL SECURITY INVOKER:訪問視圖的用戶必須對視圖所訪問的表具備select權限。 缺省SQL SECURITY選項等同於SQL SECURITY DEFINER 視圖權限總結: 使用root用戶定義一個視圖(推薦使用第一種):u一、u2 1)u1做爲定義者定義一個視圖,u1對基表有select權限,u2對視圖有訪問權限:u2是以定義者的身份訪問能夠查詢到基表的內容; 2)u1做爲定義者定義一個視圖,u1對基表沒有select權限,u2對視圖有訪問權限,u2對基表有select權限:u2訪問視圖的時候是以調用者的身份,此時調用者是u2,能夠查詢到基表的內容。
6、視圖查詢語句的處理
示例:全部有罰款的球員的信息
mysql> create view cost_raisers -> as -> select * from PLAYERS -> where playerno in (select playerno from PENALTIES);
mysql> select playerno from cost_raisers -> where town='Stratford'; +----------+ | PLAYERNO | +----------+ | 6 | +----------+
# 先把select語句中的視圖名使用定義視圖的select語句來替代; # 再處理所獲得的select語句。 mysql> select playerno from -> ( -> select * from PLAYERS -> where playerno in-> (select playerno from PENALTIES) -> )as viewformula -> where town='Stratford'; +----------+ | PLAYERNO | +----------+ | 6 | +----------+
先處理定義視圖的select語句,這會生成一箇中間的結果集; 而後,再在中間結果上執行select查詢。 mysql> select <列名> from <中間結果>;
2、存儲過程
存儲過程(Stored Procedure)是一種在數據庫中存儲複雜程序,以便外部程序調用的一種數據庫對象。
存儲過程是爲了完成特定功能的SQL語句集,經編譯建立並保存在數據庫中,用戶可經過指定存儲過程的名字並給定參數(須要時)來調用執行。
存儲過程思想上很簡單,就是數據庫 SQL 語言層面的代碼封裝與重用。
一.建立存儲過程
create procedure sp_name()
begin
.........
end
二.調用存儲過程
1.基本語法:call sp_name()
注意:存儲過程名稱後面必須加括號,哪怕該存儲過程沒有參數傳遞
三.刪除存儲過程
1.基本語法:
drop procedure sp_name//
2.注意事項
(1)不能在一個存儲過程當中刪除另外一個存儲過程,只能調用另外一個存儲過程
四.其餘經常使用命令
1.show procedure status
顯示數據庫中全部存儲的存儲過程基本信息,包括所屬數據庫,存儲過程名稱,建立時間等
2.show create procedure sp_name
顯示某一個MySQL存儲過程的詳細信息
5、存儲過程實例
一、建立存儲過程
-- 建立存儲過程 delimiter // create procedure p1() BEGIN select * from t1; END// delimiter ; -- 執行存儲過程 call p1() 無參數存儲過程
對於存儲過程,能夠接收參數,其參數有三類:
-- 建立存儲過程 delimiter \\ create procedure p1( in i1 int, in i2 int, inout i3 int, out r1 int ) BEGIN DECLARE temp1 int; DECLARE temp2 int default 0; set temp1 = 1; set r1 = i1 + i2 + temp1 + temp2; set i3 = i3 + 100; end\\ delimiter ; -- 執行存儲過程 set @t1 =4; set @t2 = 0; CALL p1 (1, 2 ,@t1, @t2); SELECT @t1,@t2; 有參數的存儲過程
delimiter // create procedure p1() begin select * from v1; end // delimiter ;
delimiter // create procedure p2( in n1 int, inout n3 int, out n2 int, ) begin declare temp1 int ; declare temp2 int default 0; select * from v1; set n2 = n1 + 100; set n3 = n3 + n1 + 100; end // delimiter ; 2. 結果集+out值
delimiter \\ create PROCEDURE p1( 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 tb2(name)values('seven'); COMMIT; -- SUCCESS set p_return_code = 0; END\\ delimiter ;
delimiter // create procedure p3() begin declare ssid int; -- 自定義變量1 declare ssname varchar(50); -- 自定義變量2 DECLARE done INT DEFAULT FALSE; DECLARE my_cursor CURSOR FOR select sid,sname from student; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; open my_cursor; xxoo: LOOP fetch my_cursor into ssid,ssname; if done then leave xxoo; END IF; insert into teacher(tname) values(ssname); end loop xxoo; close my_cursor; end // delimter ;
delimiter \\ CREATE PROCEDURE p4 ( in nid int ) BEGIN PREPARE prod FROM 'select * from student where sid > ?'; EXECUTE prod USING @nid; DEALLOCATE prepare prod; END\\ delimiter ; 5. 動態執行SQL
二、刪除存儲過程
drop procedure proc_name;
三、執行存儲過程
-- 無參數 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) 執行存儲過程
#!/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) pymysql執行存儲過程
3、觸發器
若是但願在對某張表的增、刪、改的先後進行觸發某個特定的行爲時,可使用觸發器來自定義操做,觸發器用於定製用戶對錶的行進行【增/刪/改】先後的行爲。
在MySQL中,建立觸發器語法以下:
CREATE TRIGGER trigger_name
trigger_time
trigger_event ON tbl_name
FOR EACH ROW
trigger_stmt
trigger_name:標識觸發器名稱,用戶自行指定;
trigger_time:標識觸發時機,取值爲 BEFORE 或 AFTER;
trigger_event:標識觸發事件,取值爲 INSERT、UPDATE 或 DELETE;
tbl_name:標識創建觸發器的表名,即在哪張表上創建觸發器;
trigger_stmt:觸發器程序體,能夠是一句SQL語句,或者用 BEGIN 和 END 包含的多條語句。
因而可知,能夠創建6種觸發器,即:BEFORE INSERT、BEFORE UPDATE、BEFORE DELETE、AFTER INSERT、AFTER UPDATE、AFTER DELETE。
另外有一個限制是不能同時在一個表上創建2個相同類型的觸發器,所以在一個表上最多創建6個觸發器。
trigger_event 詳解
MySQL 除了對 INSERT、UPDATE、DELETE 基本操做進行定義外,還定義了 LOAD DATA 和 REPLACE 語句,這兩種語句也能引發上述6中類型的觸發器的觸發。
LOAD DATA 語句用於將一個文件裝入到一個數據表中,至關與一系列的 INSERT 操做。
REPLACE 語句通常來講和 INSERT 語句很像,只是在表中有 primary key 或 unique 索引時,若是插入的數據和原來 primary key 或 unique 索引一致時,會先刪除原來的數據,而後增長一條新數據,也就是說,一條 REPLACE 語句有時候等價於一條。
INSERT 語句,有時候等價於一條 DELETE 語句加上一條 INSERT 語句。
INSERT 型觸發器:插入某一行時激活觸發器,可能經過 INSERT、LOAD DATA、REPLACE 語句觸發;
UPDATE 型觸發器:更改某一行時激活觸發器,可能經過 UPDATE 語句觸發;
DELETE 型觸發器:刪除某一行時激活觸發器,可能經過 DELETE、REPLACE 語句觸發。
BEGIN … END 詳解
在MySQL中,BEGIN … END 語句的語法爲:
BEGIN
[statement_list]
END
其中,statement_list 表明一個或多個語句的列表,列表內的每條語句都必須用分號(;)來結尾。
而在MySQL中,分號是語句結束的標識符,遇到分號表示該段語句已經結束,MySQL能夠開始執行了。所以,解釋器遇到statement_list 中的分號後就開始執行,而後會報出錯誤,由於沒有找到和 BEGIN 匹配的 END。
這時就會用到 DELIMITER 命令(DELIMITER 是定界符,分隔符的意思),它是一條命令,不須要語句結束標識,語法爲:
DELIMITER new_delemiter
new_delemiter 能夠設爲1個或多個長度的符號,默認的是分號(;),咱們能夠把它修改成其餘符號,如$:
DELIMITER $
在這以後的語句,以分號結束,解釋器不會有什麼反應,只有遇到了$,才認爲是語句結束。注意,使用完以後,咱們還應該記得把它給修改回來。
# 假設系統中有兩個表: # 班級表 class(班級號 classID, 班內學生數 stuCount) # 學生表 student(學號 stuID, 所屬班級號 classID) # 要建立觸發器來使班級表中的班內學生數隨着學生的添加自動更新,代碼以下: DELIMITER $ create trigger tri_stuInsert after insert on student for each row begin declare c int; set c = (select stuCount from class where classID=new.classID); update class set stuCount = c + 1 where classID = new.classID; end$ DELIMITER ;
MySQL 中使用 DECLARE 來定義一局部變量,該變量只能在 BEGIN … END 複合語句中使用,而且應該定義在複合語句的開頭,
即其它語句以前,語法以下:
DECLARE var_name[,...] type [DEFAULT value]
其中:
var_name 爲變量名稱,同 SQL 語句同樣,變量名不區分大小寫;type 爲 MySQL 支持的任何數據類型;能夠同時定義多個同類型的變量,用逗號隔開;變量初始值爲 NULL,若是須要,可使用 DEFAULT 子句提供默認值,值能夠被指定爲一個表達式。
在 INSERT 型觸發器中,NEW 用來表示將要(BEFORE)或已經(AFTER)插入的新數據;
在 UPDATE 型觸發器中,OLD 用來表示將要或已經被修改的原數據,NEW 用來表示將要或已經修改成的新數據;
在 DELETE 型觸發器中,OLD 用來表示將要或已經被刪除的原數據;
使用方法: NEW.columnName (columnName 爲相應數據表某一列名)
另外,OLD 是隻讀的,而 NEW 則能夠在觸發器中使用 SET 賦值,這樣不會再次觸發觸發器,形成循環調用(如每插入一個學生前,都在其學號前加「2013」)。
SET var_name = expr [,var_name = expr] ...
SHOW TRIGGERS [FROM schema_name]; # 其中,schema_name 即 Schema 的名稱,在 MySQL 中 Schema 和 Database 是同樣的,也就是說,能夠指定數據庫名,這樣就 # 沒必要先「USE database_name;」了。
DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name
咱們創建的數據庫通常都是 InnoDB 數據庫,其上創建的表是事務性表,也就是事務安全的。這時,若SQL語句或觸發器執行失敗,MySQL 會回滾事務,有:
1.索引簡介:索引是表的目錄,在查找內容以前能夠先在目錄中查找索引位置,以此快速定位查詢數據。對於索引,會保存在額外的文件中。
2.索引做用:加速查找+約束
3.索引種類:
主鍵索引:加速查找、不重複、非空
惟一索引:加速查找、不重複
普通索引:加速查找
聯合索引:加速查找
聯合惟一索引:加速查找、不重複
PS:聯合索引遵循最左前綴原則
id name pwd email 假設name,pwd,email 創建聯合索引 select * from name='xx'; 命中索引 select * from name='xx' and pwd='123'; 命中索引 select * from name='xx' and pwd='123' and email='qq'; 命中索引 select * from name='xx' and emai='qq'; 命中索引 select * from email='qq' and pwd='123'; 不能命中索引
覆蓋索引:select的數據列只用從索引中就可以取得,沒必要讀取數據行,換句話說查詢列要被所建的索引覆蓋,如索引爲name,也僅查找name列
索引合併:使用多個單列索引去查找數據,如name和age 都爲索引,使用name和age聯合查詢
4.建立索引語法
--建立表時 CREATE TABLE 表名 ( 字段名1 數據類型 [完整性約束條件…], 字段名2 數據類型 [完整性約束條件…], [UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY [索引名] (字段名[(長度)] [ASC |DESC]) );
CREATE TABLE test2( id INT, name VARCHAR(20), INDEX index_name (name) );
---CREATE在已存在的表上建立索引 CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 ON 表名 (字段名[(長度)] [ASC |DESC]) ; ---ALTER TABLE在已存在的表上建立索引 ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 (字段名[(長度)] [ASC |DESC]) ; CREATE INDEX index_emp_name on emp1(name); ALTER TABLE emp2 ADD UNIQUE INDEX index_bank_num(band_num);
# 語法:DROP INDEX 索引名 on 表名 DROP INDEX index_emp_name on emp1; DROP INDEX bank_num on emp2;
5.索引測試實驗
--建立表 create table t1(id int,name varchar(20)); --存儲過程 delimiter $$ create procedure autoinsert() BEGIN declare i int default 1; while(i<5000)do insert into t1 values(i,'yuan'); set i=i+1; end while; END$$ delimiter ; --調用函數 call autoinsert(); -- 花費時間比較: -- 建立索引前 select * from t1 where id=300000;--0.32s -- 添加索引 create index index_id on t1(id); -- 建立索引後 select * from Indexdb.t1 where id=300000;--0.00s --刪除索引 drop index index_id on t1;
use crawed; desc doutula; select count(*) from doutula; +----------+ | count(*) | +----------+ | 27308 | +----------+ select name from doutula where name like '%壞蛋%'; --34 rows in set (0.53 sec) create index index_name on doutula (name); select name from doutula where name like '%壞蛋%'; --34 rows in set (0.05 sec)
6.正確使用索引
數據庫表中添加索引後確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,若是以錯誤的方式使用,則即便創建索引也會不奏效。
即便創建索引,索引也不會生效:
like '%xx' select * from tb1 where name like '%cn'; - 使用函數 select * from tb1 where reverse(name) = 'wupeiqi'; - or select * from tb1 where nid = 1 or email = 'seven@live.com'; 特別的:當or條件中有未創建索引的列才失效,如下會走索引 select * from tb1 where nid = 1 or name = 'seven'; select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex' - 類型不一致 若是列是字符串類型,傳入條件是必須用引號引發來,否則... select * from tb1 where name = 999; - != select * from tb1 where name != 'alex' 特別的:若是是主鍵,則仍是會走索引 select * from tb1 where nid != 123 - > select * from tb1 where name > 'alex' 特別的:若是是主鍵或索引是整數類型,則仍是會走索引 select * from tb1 where nid > 123 select * from tb1 where num > 123 - order by select email from tb1 order by name desc; 當根據索引排序時候,選擇的映射若是不是索引,則不走索引 特別的:若是對主鍵排序,則仍是走索引: select * from tb1 order by nid desc; - 組合索引最左前綴 若是組合索引爲:(name,email) name and email -- 使用索引 name -- 使用索引 email -- 不使用索引
5、函數
mysql提供了許多內置函數
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' 部份內置函數
delimiter \\ create function f1( i1 int, i2 int) returns int BEGIN declare num int; set num = i1 + i2; return(num); END \\ delimiter ;
drop function func_name;
# 獲取返回值 declare @i VARCHAR(32); select UPPER('alex') into @i; SELECT @i; # 在查詢中使用 select f1(11,nid) ,name from tb2;
mysql> select concat('M','y','SQL'); +-----------------------+ | concat('M','y','SQL') | +-----------------------+ | MySQL | +-----------------------+ 1 row in set (0.00 sec) mysql> select concat('M','y','SQL','5.7'); +-----------------------------+ | concat('M','y','SQL','5.7') | +-----------------------------+ | MySQL5.7 | +-----------------------------+ 1 row in set (0.00 sec) mysql> select concat('M','y','SQL',' 5.7'); +------------------------------+ | concat('M','y','SQL',' 5.7') | +------------------------------+ | MySQL 5.7 | +------------------------------+ 1 row in set (0.00 sec) mysql> SELECT concat_ws("-",'2012','09'); +----------------------------+ | concat_ws("-",'2012','09') | +----------------------------+ | 2012-09 | +----------------------------+ 1 row in set (0.00 sec) mysql> SELECT concat_ws(":",'2012','09'); +----------------------------+ | concat_ws(":",'2012','09') | +----------------------------+ | 2012:09 | +----------------------------+ 1 row in set (0.00 sec) mysql> SELECT concat_ws("-:",'2012','09'); +-----------------------------+ | concat_ws("-:",'2012','09') | +-----------------------------+ | 2012-:09 | +-----------------------------+ 1 row in set (0.00 sec) mysql> SELECT concat_ws(":-",'2012','09'); +-----------------------------+ | concat_ws(":-",'2012','09') | +-----------------------------+ | 2012:-09 | +-----------------------------+ 1 row in set (0.00 sec) mysql> SELECT concat_ws(null,'2012','09'); +-----------------------------+ | concat_ws(null,'2012','09') | +-----------------------------+ | NULL | +-----------------------------+ 1 row in set (0.00 sec) mysql> select concat(1,2); +-------------+ | concat(1,2) | +-------------+ | 12 | +-------------+ 1 row in set (0.00 sec) mysql> select strcmp('ac','ac'); +-------------------+ | strcmp('ac','ac') | +-------------------+ | 0 | +-------------------+ 1 row in set (0.06 sec) mysql> select strcmp('ab','ac'); +-------------------+ | strcmp('ab','ac') | +-------------------+ | -1 | +-------------------+ 1 row in set (0.00 sec) mysql> select strcmp('ac','ab'); +-------------------+ | strcmp('ac','ab') | +-------------------+ | 1 | +-------------------+ 1 row in set (0.00 sec) mysql> help length; Name: 'LENGTH' Description: Syntax: LENGTH(str) Returns the length of the string str, measured in bytes. A multibyte character counts as multiple bytes. This means that for a string containing five 2-byte characters, LENGTH() returns 10, whereas CHAR_LENGTH() returns 5. URL: http://dev.mysql.com/doc/refman/5.7/en/string-functions.html Examples: mysql> SELECT LENGTH('text'); -> 4 mysql> select length('1 2'); +---------------+ | length('1 2') | +---------------+ | 3 | +---------------+ 1 row in set (0.00 sec) mysql> select length('1 2 '); +----------------+ | length('1 2 ') | +----------------+ | 4 | +----------------+ 1 row in set (0.00 sec) mysql> select length(' 1 2 '); +-----------------+ | length(' 1 2 ') | +-----------------+ | 5 | +-----------------+ 1 row in set (0.00 sec) mysql> help charlength; Nothing found Please try to run 'help contents' for a list of all accessible topics mysql> help char_length; Name: 'CHAR_LENGTH' Description: Syntax: CHAR_LENGTH(str) Returns the length of the string str, measured in characters. A multibyte character counts as a single character. This means that for a string containing five 2-byte characters, LENGTH() returns 10, whereas CHAR_LENGTH() returns 5. URL: http://dev.mysql.com/doc/refman/5.7/en/string-functions.html mysql> select char_length(hello world); ERROR 1583 (42000): Incorrect parameters in the call to native function 'char_le ngth' mysql> select char_length('hello world'); +----------------------------+ | char_length('hello world') | +----------------------------+ | 11 | +----------------------------+ 1 row in set (0.00 sec) mysql> select upper('ADSDAsdadsf'); +----------------------+ | upper('ADSDAsdadsf') | +----------------------+ | ADSDASDADSF | +----------------------+ 1 row in set (0.02 sec) mysql> select ucase('ADSs'); +---------------+ | ucase('ADSs') | +---------------+ | ADSS | +---------------+ 1 row in set (0.00 sec) mysql> select lower('ADSs'); +---------------+ | lower('ADSs') | +---------------+ | adss | +---------------+ 1 row in set (0.00 sec) mysql> select find_in_set('MySQL','a,b,c,MySQL'); +------------------------------------+ | find_in_set('MySQL','a,b,c,MySQL') | +------------------------------------+ | 4 | +------------------------------------+ 1 row in set (0.08 sec) mysql> help field; Name: 'FIELD' Description: Syntax: FIELD(str,str1,str2,str3,...) Returns the index (position) of str in the str1, str2, str Returns 0 if str is not found. If all arguments to FIELD() are strings, all arguments are strings. If all arguments are numbers, they are compared a Otherwise, the arguments are compared as double. If str is NULL, the return value is 0 because NULL fails e comparison with any value. FIELD() is the complement of EL URL: http://dev.mysql.com/doc/refman/5.7/en/string-functio Examples: mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo -> 2 mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo -> 0 mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo +------------------------------------------------+ | FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo') | +------------------------------------------------+ | 2 | +------------------------------------------------+ 1 row in set (0.05 sec) mysql> select left("2013-09-28 23:58:54"); ERROR 1064 (42000): You have an error in your SQL syntax; corresponds to your MySQL server version for the right syn line 1 mysql> select left("2013-09-28 23:58:54","10"); +----------------------------------+ | left("2013-09-28 23:58:54","10") | +----------------------------------+ | 2013-09-28 | +----------------------------------+ 1 row in set (0.04 sec) mysql> select right("2013-09-28 23:58:54","10"); +-----------------------------------+ | right("2013-09-28 23:58:54","10") | +-----------------------------------+ | 8 23:58:54 | +-----------------------------------+ 1 row in set (0.00 sec) mysql> select right("2013-09-28 23:58:54",10); +---------------------------------+ | right("2013-09-28 23:58:54",10) | +---------------------------------+ | 8 23:58:54 | +---------------------------------+ 1 row in set (0.00 sec) mysql> select substring("this is test string",6,2); +--------------------------------------+ | substring("this is test string",6,2) | +--------------------------------------+ | is | +--------------------------------------+ 1 row in set (0.00 sec) mysql> select substring("this is test string",6,200); +----------------------------------------+ | substring("this is test string",6,200) | +----------------------------------------+ | is test string | +----------------------------------------+ 1 row in set (0.00 sec) mysql> select mid("this is test string",6,200); +----------------------------------+ | mid("this is test string",6,200) | +----------------------------------+ | is test string | +----------------------------------+ 1 row in set (0.00 sec) mysql> help mid; Name: 'MID' Description: Syntax: MID(str,pos,len) MID(str,pos,len) is a synonym for SUBSTRING(str,pos,len). URL: http://dev.mysql.com/doc/refman/5.7/en/string-functio mysql> select ltrim("1 2"); +--------------+ | ltrim("1 2") | +--------------+ | 1 2 | +--------------+ 1 row in set (0.06 sec) mysql> help trim; Name: 'TRIM' Description: Syntax: TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRI FROM] str) Returns the string str with all remstr prefixes or suffixe none of the specifiers BOTH, LEADING, or TRAILING is given assumed. remstr is optional and, if not specified, spaces URL: http://dev.mysql.com/doc/refman/5.7/en/string-functio Examples: 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' mysql> select replace('this is test string','is',"is not") +----------------------------------------------+ | replace('this is test string','is',"is not") | +----------------------------------------------+ | this not is not test string | +----------------------------------------------+ 1 row in set (0.00 sec) mysql> select rand(); +--------------------+ | rand() | +--------------------+ | 0.4352682404548565 | +--------------------+ 1 row in set (0.06 sec) mysql> select rand(3); +--------------------+ | rand(3) | +--------------------+ | 0.9057697559760601 | +--------------------+ 1 row in set (0.00 sec) mysql> help rand; Name: 'RAND' Description: Syntax: RAND(), RAND(N) Returns a random floating-point value v in the range 0 <= constant integer argument N is specified, it is used as th which produces a repeatable sequence of column values. In example, note that the sequences of values produced by RAN same both places where it occurs. URL: http://dev.mysql.com/doc/refman/5.7/en/mathematical-f Examples: mysql> CREATE TABLE t (i INT); Query OK, 0 rows affected (0.42 sec) mysql> INSERT INTO t VALUES(1),(2),(3); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT i, RAND() FROM t; +------+------------------+ | i | RAND() | +------+------------------+ | 1 | 0.61914388706828 | | 2 | 0.93845168309142 | | 3 | 0.83482678498591 | +------+------------------+ 3 rows in set (0.00 sec) mysql> SELECT i, RAND(3) FROM t; +------+------------------+ | i | RAND(3) | +------+------------------+ | 1 | 0.90576975597606 | | 2 | 0.37307905813035 | | 3 | 0.14808605345719 | +------+------------------+ 3 rows in set (0.00 sec) mysql> SELECT i, RAND() FROM t; +------+------------------+ | i | RAND() | +------+------------------+ | 1 | 0.35877890638893 | | 2 | 0.28941420772058 | | 3 | 0.37073435016976 | +------+------------------+ 3 rows in set (0.00 sec) mysql> SELECT i, RAND(3) FROM t; +------+------------------+ | i | RAND(3) | +------+------------------+ | 1 | 0.90576975597606 | | 2 | 0.37307905813035 | | 3 | 0.14808605345719 | +------+------------------+ 3 rows in set (0.01 sec) mysql> select ceil(5.6); +-----------+ | ceil(5.6) | +-----------+ | 6 | +-----------+ 1 row in set (0.00 sec) mysql> select floor(5.6); +------------+ | floor(5.6) | +------------+ | 5 | +------------+ 1 row in set (0.00 sec) mysql> select floor(5.1); +------------+ | floor(5.1) | +------------+ | 5 | +------------+ 1 row in set (0.00 sec) mysql> select floor(5.9); +------------+ | floor(5.9) | +------------+ | 5 | +------------+ 1 row in set (0.00 sec) mysql> select truncat(123.456,2); ERROR 1046 (3D000): No database selected mysql> select truncate(123.456,2); +---------------------+ | truncate(123.456,2) | +---------------------+ | 123.45 | +---------------------+ 1 row in set (0.00 sec) mysql> select truncate(123.456,-2); +----------------------+ | truncate(123.456,-2) | +----------------------+ | 100 | +----------------------+ 1 row in set (0.00 sec) mysql> select truncate(123.456,-1); +----------------------+ | truncate(123.456,-1) | +----------------------+ | 120 | +----------------------+ 1 row in set (0.00 sec) mysql> select round(123.456); +----------------+ | round(123.456) | +----------------+ | 123 | +----------------+ 1 row in set (0.00 sec) mysql> select round(123.456,2); +------------------+ | round(123.456,2) | +------------------+ | 123.46 | +------------------+ 1 row in set (0.00 sec) mysql> select now(); +---------------------+ | now() | +---------------------+ | 2018-01-09 11:12:25 | +---------------------+ 1 row in set (0.00 sec) mysql> select curdate(); +------------+ | curdate() | +------------+ | 2018-01-09 | +------------+ 1 row in set (0.06 sec) mysql> select from_unixitime("123"); ERROR 1046 (3D000): No database selected mysql> select from_unixtime("123"); +----------------------------+ | from_unixtime("123") | +----------------------------+ | 1970-01-01 08:02:03.000000 | +----------------------------+ 1 row in set (0.07 sec) mysql> select unix_timestamp(now()); +-----------------------+ | unix_timestamp(now()) | +-----------------------+ | 1515467669 | +-----------------------+ 1 row in set (0.00 sec) mysql> select sysdate(); +---------------------+ | sysdate() | +---------------------+ | 2018-01-09 11:15:00 | +---------------------+ 1 row in set (0.00 sec) mysql> select year(now()); +-------------+ | year(now()) | +-------------+ | 2018 | +-------------+ 1 row in set (0.00 sec) mysql> select hour(now()); +-------------+ | hour(now()) | +-------------+ | 11 | +-------------+ 1 row in set (0.02 sec) mysql> select to_days('20'); +---------------+ | to_days('20') | +---------------+ | NULL | +---------------+ 1 row in set, 1 warning (0.07 sec) mysql> select to_days('2013-4-22'); +----------------------+ | to_days('2013-4-22') | +----------------------+ | 735345 | +----------------------+ 1 row in set (0.00 sec) mysql> \h For information about MySQL products and services, visit: http://www.mysql.com/ For developer information, including the MySQL Reference M http://dev.mysql.com/ To buy MySQL Enterprise support, training, or other produc https://shop.mysql.com/ List of all MySQL commands: Note that all text commands must be first on line and end ? (\?) Synonym for `help'. clear (\c) Clear the current input statement. connect (\r) Reconnect to the server. Optional arguments delimiter (\d) Set statement delimiter. ego (\G) Send command to mysql server, display resul exit (\q) Exit mysql. Same as quit. go (\g) Send command to mysql server. help (\h) Display this help. notee (\t) Don't write into outfile. print (\p) Print current command. prompt (\R) Change your mysql prompt. quit (\q) Quit mysql. rehash (\#) Rebuild completion hash. source (\.) Execute an SQL script file. Takes a file na status (\s) Get status information from the server. tee (\T) Set outfile [to_outfile]. Append everything use (\u) Use another database. Takes database name a charset (\C) Switch to another charset. Might be needed with multi-byte charsets. warnings (\W) Show warnings after every statement. nowarning (\w) Don't show warnings after every statement. resetconnection(\x) Clean session context. For server side help, type 'help contents' mysql> \s -------------- mysql Ver 14.14 Distrib 5.7.17, for Win64 (x86_64) Connection id: 20 Current database: Current user: root@localhost SSL: Not in use Using delimiter: ; Server version: 5.7.17-log MySQL Community Server (GPL) Protocol version: 10 Connection: localhost via TCP/IP Server characterset: utf8 Db characterset: utf8 Client characterset: gbk Conn. characterset: gbk TCP port: 3306 Uptime: 1 day 21 hours 34 min 49 sec Threads: 3 Questions: 1081 Slow queries: 0 Opens: 314 Flush tables: 1 Open tables: 267 Queries per second avg: 0.006 -------------- mysql> select user(); +----------------+ | user() | +----------------+ | root@localhost | +----------------+ 1 row in set (0.00 sec) mysql> select version; ERROR 1054 (42S22): Unknown column 'version' in 'field list' mysql> select version(); +------------+ | version() | +------------+ | 5.7.17-log | +------------+ 1 row in set (0.00 sec) mysql> create table auto_test(id int auto_increment); ERROR 1046 (3D000): No database selected mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | company | | index_test | | mysql | | num | | performance_schema | | sakila | | sys | | table_test | | test | | world | +--------------------+ 11 rows in set (0.00 sec) mysql> use test; Database changed mysql> create table auto_test(id int auto_increment primary key); Query OK, 0 rows affected (0.81 sec) mysql> show create table auto_increment; ERROR 1146 (42S02): Table 'test.auto_increment' doesn't exist mysql> show create table auto_test; +-----------+------------------------------------------------------------------- -----------------------------------------------------------+ | Table | Create Table | +-----------+------------------------------------------------------------------- -----------------------------------------------------------+ | auto_test | CREATE TABLE `auto_test` ( `id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +-----------+------------------------------------------------------------------- -----------------------------------------------------------+ 1 row in set (0.00 sec) mysql> insert into auto_test values(null); Query OK, 1 row affected (0.11 sec) mysql> insert into auto_test values(null); Query OK, 1 row affected (0.05 sec) mysql> insert into auto_test values(null); Query OK, 1 row affected (0.09 sec) mysql> insert into auto_test values(null); Query OK, 1 row affected (0.23 sec) mysql> select last_insert_id(); +------------------+ | last_insert_id() | +------------------+ | 4 | +------------------+ 1 row in set (0.00 sec) mysql> select * from auto_test; +----+ | id | +----+ | 1 | | 2 | | 3 | | 4 | +----+ 4 rows in set (0.00 sec) mysql> insert into auto_test values(null); Query OK, 1 row affected (0.14 sec) mysql> select last_insert_id(); +------------------+ | last_insert_id() | +------------------+ | 5 | +------------------+ 1 row in set (0.00 sec) mysql> select * from auto_test; +----+ | id | +----+ | 1 | | 2 | | 3 | | 4 | | 5 | +----+ 5 rows in set (0.00 sec) mysql> help ifnull; Name: 'IFNULL' Description: Syntax: IFNULL(expr1,expr2) If expr1 is not NULL, IFNULL() returns expr1; otherwise it returns expr2. IFNULL() returns a numeric or string value, depending on the context in which it is used. URL: http://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html Examples: mysql> SELECT IFNULL(1,0); -> 1 mysql> SELECT IFNULL(NULL,10); -> 10 mysql> SELECT IFNULL(1/0,10); -> 10 mysql> SELECT IFNULL(1/0,'yes'); -> 'yes' mysql> SELECT IFNULL(1,0); +-------------+ | IFNULL(1,0) | +-------------+ | 1 | +-------------+ 1 row in set (0.00 sec) mysql> password; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'passw ord' at line 1 mysql> password(); ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'passw ord()' at line 1 mysql> help password(); Nothing found Please try to run 'help contents' for a list of all accessible topics mysql> help password; Name: 'PASSWORD' Description: Syntax: PASSWORD(str) *Note*: This function is deprecated as of MySQL 5.7.6 and will be removed in a future MySQL release. Returns a hashed password string calculated from the cleartext password str. The return value is a nonbinary string in the connection character set, or NULL if the argument is NULL. This function is the SQL interface to the algorithm used by the server to encrypt MySQL passwords for storage in the mysql.user grant table. The old_passwords system variable controls the password hashing method used by the PASSWORD() function. It also influences password hashing performed by CREATE USER and GRANT statements that specify a password using an IDENTIFIED BY clause. URL: http://dev.mysql.com/doc/refman/5.7/en/encryption-functions.html Examples: mysql> SET old_passwords = 0; mysql> SELECT PASSWORD('mypass'), OLD_PASSWORD('mypass'); +-------------------------------------------+------------------------+ | PASSWORD('mypass') | OLD_PASSWORD('mypass') | +-------------------------------------------+------------------------+ | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 | 6f8c114b58f2ce9e | +-------------------------------------------+------------------------+ mysql> SET old_passwords = 1; mysql> SELECT PASSWORD('mypass'), OLD_PASSWORD('mypass'); +--------------------+------------------------+ | PASSWORD('mypass') | OLD_PASSWORD('mypass') | +--------------------+------------------------+ | 6f8c114b58f2ce9e | 6f8c114b58f2ce9e | +--------------------+------------------------+
6、事務
事務指邏輯上的一組操做,組成這組操做的各個單元,要不所有成功,要不所有不成功。
數據庫開啓事務命令
-- start transaction 開啓事務
-- Rollback 回滾事務,即撤銷指定的sql語句(只能回退insert delete update語句),回滾到上一次commit的位置
-- Commit 提交事務,提交未存儲的事務
-- savepoint 保留點 ,事務處理中設置的臨時佔位符 你能夠對它發佈回退(與整個事務回退不一樣)
轉帳實例:
select * from test; +------+-------+--------+ | id | name | salary | +------+-------+--------+ | 1 | zhang | 8000 | | 2 | fei | 10000 | | 3 | kobe | 8000 | | 4 | james | 9000 | +------+-------+--------+ 4 rows in set (0.00 sec) start transaction; update test set salary=salary-5000 where id=2; rollback; update test set salary=salary-5000 where id=2; update test set salary=salary+5000 where id=1; commit; savepoint create table test2(id int PRIMARY KEY auto_increment,name VARCHAR(20)) engine=innodb; INSERT INTO test2(name) VALUE ("alvin"), ("yuan"), ("xialv"); start transaction; insert into test2 (name)values('silv'); select * from test2; commit; -- 保留點 start transaction; insert into test2 (name)values('wu'); savepoint insert_wu; select * from test2; delete from test2 where id=4; savepoint delete1; select * from test2; delete from test2 where id=1; savepoint delete2; select * from test2; rollback to delete1; select * from test2; savepoint
事務特性
<1> 原子性(Atomicity):原子性是指事務是一個不可分割的工做單位,事務中的操做要麼都發生,要麼都不發生。
<2> 一致性(Consistency):事務先後數據的完整性必須保持一致。在事務執行以前數據庫是符合數據完整性約束的,不管事務是否執行成功,事務結束後的數據庫中的數據也應該是符合完整性約束的。在某一時間點,若是數據庫中的全部記錄都能保證知足當前數據庫中的全部約束,則能夠說當前的數據庫是符合數據完整性約束的。 好比刪部門表前應該刪掉關聯員工(已經創建外鍵),若是數據庫服務器發生錯誤,有一個員工沒刪掉,那麼此時員工的部門表已經刪除,那麼就不符合完整性約束了,因此這樣的數據庫也就性能太差啦! <3>隔離性(Isolation):事務的隔離性是指多個用戶併發訪問數據庫時,一個用戶的事務不能被其它用戶的事務所幹擾,多個併發事務之間數據要相互隔離。 <4>持久性(Durability):持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即便數據庫發生故障也不該該對其有任何影響。
四個隔離級別:
安全性考慮:Serializable>Repeatable read>Read committed>Read uncommitted
數據庫效率:Read uncommitted>Read committed>Repeatable read>Serializable
通常狀況下,咱們會使用Repeatable read、Read committed mysql數據庫默認的數據庫隔離級別Repeatable read
mysql中設置數據庫的隔離級別語句:set
[
global
/session]
transaction
isolation
level
xxxx;
若是使用global則修改的是數據庫的默認隔離級別,全部新開的窗口的隔離級別繼承自這個默認隔離級別若是使用session修改,則修改的是當前客戶端的隔離級別,和數據庫默認隔離級別無關。當前的客戶端是什麼隔離級別,就能防止什麼隔離級別問題,和其餘客戶端是什麼隔離級別無關。
mysql中設置數據庫的隔離級別語句:select
@@tx_isolation;
7、數據庫受權
1. 建立用戶
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
%
CREATE USER 'dog'@'localhost' IDENTIFIED BY '123456'; CREATE USER 'pig'@'192.168.1.101_' IDENDIFIED BY '123456'; CREATE USER 'pig'@'%' IDENTIFIED BY '123456'; CREATE USER 'pig'@'%' IDENTIFIED BY ''; CREATE USER 'pig'@'%';
GRANT privileges ON databasename.tablename TO 'username'@'host'
SELECT
,INSERT
,UPDATE
等,若是要授予所的權限則使用ALL
*
表示,如*.*
GRANT SELECT, INSERT ON test.user TO 'pig'@'%'; GRANT ALL ON *.* TO 'pig'@'%'; GRANT ALL ON maindataplus.* TO 'pig'@'%';
用以上命令受權的用戶不能給其它用戶受權,若是想讓該用戶能夠受權,用如下命令:
GRANT privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION;
SET PASSWORD FOR 'username'@'host' = PASSWORD('newpassword');
若是是當前登錄用戶用:
SET PASSWORD = PASSWORD("newpassword");
SET PASSWORD FOR 'pig'@'%' = PASSWORD("123456");
REVOKE privilege ON databasename.tablename FROM 'username'@'host';
privilege, databasename, tablename:同受權部分
REVOKE SELECT ON *.* FROM 'pig'@'%';
假如你在給用戶'pig'@'%'
受權的時候是這樣的(或相似的):GRANT SELECT ON test.user TO 'pig'@'%'
,則在使用REVOKE SELECT ON *.* FROM 'pig'@'%';
命令並不能撤銷該用戶對test數據庫中user表的SELECT
操做。相反,若是受權使用的是GRANT SELECT ON *.* TO 'pig'@'%';
則REVOKE SELECT ON test.user FROM 'pig'@'%';
命令也不能撤銷該用戶對test數據庫中user表的Select
權限。
具體信息能夠用命令SHOW GRANTS FOR 'pig'@'%';
查看。
DROP USER 'username'@'host';
8、Python關於MySQL的API接口-pymysql模塊
pymsql是Python中操做MySQL的模塊,其使用方法和py2的MySQLdb幾乎相同。
安裝:pip install pymysql
代碼:
# -*- coding: utf-8 -*-
import pymysql
#1.鏈接mysql
conn = pymysql.connect(host='localhost',port=3306,user='root',password='0000',db='python3')
# conn = pymysql.connect(host='localhost',user='root',password='0000',db='crawed',charset='utf8',cursorclass = pymysql.cursors.DictCursor,use_unicode=True)
#2.建立遊標
cursor = conn.cursor()
# cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) #更改獲取數據結果的數據類型
#3.建立表添加數據
# sql = 'create table test(id int,name varchar(20))'
# sql1 = "insert into test values (1,'zhang'),(2,'fei');"
# cursor.execute(sql)
# cursor.execute(sql1)
#4.查詢數據
sql2 = 'select * from test;'
cursor.execute(sql2)
# num = cursor.fetchone()
# print(cursor.fetchone())
# print(cursor.fetchmany(2))
print(cursor.fetchall())
#5.scroll 控制遊標位置
# print(cursor.fetchone())
# print(cursor.fetchone())
# cursor.scroll(-1,mode='relative') # 相對當前位置移動
# cursor.scroll(0,mode='absolute') # 相對絕對位置移動
# print(cursor.fetchone())
conn.commit()
conn.close()
# import pymysql # # conn = pymysql.Connect(host='localhost', user='root', password='0000', database='flask_code', charset='utf8') # # # cursor = conn.cursor() # 每一行是元組 # cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 每一行是字典 # sql = "select * from userinfo where username='{0}' and password='{1}'".format('zhangsan','317bc264bfd3d562fa415dbb905e2d8a') # sql注入 # sql = "select * from userinfo where username='{0}' and password='{1}'".format("xx ' or 1=1 -- ",'317bc264bfd3d562fa415dbb905e2d8a') # sql = "select * from userinfo where username='%s' and password ='%s'" %("xiao ' or 1=1 -- ","47f5abdd7f4083f0cc5c94d587fa3ca4") # print(sql) # cursor.execute(sql) # cursor.execute("select * from userinfo where username=%s and password=%s",("xx ' or 1=1 --",'317bc264bfd3d562fa415dbb905e2d8a')) # cursor.execute("select * from userinfo where username=%s and password=%s",('zhangsan','317bc264bfd3d562fa415dbb905e2d8a')) # cursor.execute("select * from userinfo where username=%(us)s and password=%(pw)s",{'us':'zhangsan','pw':'317bc264bfd3d562fa415dbb905e2d8a'}) # cursor.execute("select id,username,password from userinfo where username=%(us)s and password=%(pw)s",{'us':'zhangsan','pw':'317bc264bfd3d562fa415dbb905e2d8a'}) # data = cursor.fetchall() # data = cursor.fetchone() # # print(data['id'],data['username']) # # cursor.close() # conn.close()
from DBUtils.PooledDB import PooledDB, SharedDBConnection import pymysql POOL = PooledDB( creator=pymysql, # 使用連接數據庫的模塊 maxconnections=6, # 鏈接池容許的最大鏈接數,0和None表示不限制鏈接數 mincached=2, # 初始化時,連接池中至少建立的空閒的連接,0表示不建立 maxcached=5, # 連接池中最多閒置的連接,0和None不限制 maxshared=3, # 連接池中最多共享的連接數量,0和None表示所有共享。PS: 無用,由於pymysql和MySQLdb等模塊的 threadsafety都爲1,全部值不管設置爲多少,_maxcached永遠爲0,因此永遠是全部連接都共享。 blocking=True, # 鏈接池中若是沒有可用鏈接後,是否阻塞等待。True,等待;False,不等待而後報錯 maxusage=None, # 一個連接最多被重複使用的次數,None表示無限制 setsession=[], # 開始會話前執行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服務端,檢查是否服務可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always host='127.0.0.1', port=3306, user='root', password='0000', database='flask_code', charset='utf8' )
# -*- coding: utf-8 -*- """ @Datetime: 2018/12/26 @Author: Zhang Yafei """ import pymysql from settings import POOL def connect(): conn = POOL.connection() cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) return conn, cursor def connect_close(conn, cursor): cursor.close() conn.close() def fetchone(sql, arg=list()): conn, cursor = connect() cursor.execute(sql, arg) data = cursor.fetchone() connect_close(conn, cursor) return data def fetchall(sql, arg=list()): conn, cursor = connect() cursor.execute(sql, arg) data = cursor.fetchall() connect_close(conn, cursor) return data def insert(sql, arg=list()): conn, cursor = connect() row = cursor.execute(sql, arg) conn.commit() connect_close(conn, cursor) return row
補充:數據庫優化方案
- 避免使用select * - 固定長度在前面- 內存代替表,如:性別等- 讀寫分離- 分庫- 分表 - 水平分表 - 垂直分表- 命中索引- 組合索引代替索引合併- 儘可能使用短索引- 若是取一條數據時,使用limit 1 select id,name from tb where name ='alex' limit 1;- 使用鏈接(JOIN)來代替子查詢(Sub-Queries)