數據庫學習之MySQL進階

                   數據庫進階                   

  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子句中的列名徹底相同;
  •   若是顯式的指定視圖的列名就按照指定的列名。

  注意:顯示指定視圖列名,要求視圖名後面的列的數量必須匹配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)
View Code

二、視圖一旦建立完畢,就能夠像一個普通表那樣使用,視圖主要用來查詢

  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)  
View Code

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]
alter修改視圖語法

  注意:修改視圖是指修改數據庫中已存在的表的定義,當基表的某些字段發生改變時,能夠經過修改視圖來保持視圖和基本表之間一致

三、DML操做更新視圖

  由於視圖自己沒有數據,所以對視圖進行的dml操做最終都體如今基表中 

DML更新視圖

固然,視圖的DML操做,不是全部的視圖均可以作DML操做。

①select子句中包含distinct

②select子句中包含組函數

③select語句中包含group by子句

④select語句中包含order by子句

⑤select語句中包含union 、union all等集合運算符

⑥where子句中包含相關子查詢

⑦from子句中包含多個表

⑧若是視圖中有計算列,則不能更新

⑨若是基表中有某個具備非空約束的列未出如今視圖定義中,則不能作insert操做
不能作dml操做的狀況

四、drop刪除視圖

DROP VIEW [IF EXISTS]   
view_name [, view_name] ...

mysql> drop view v_student;

  • 注:若是視圖不存在,則拋出異常;使用IF EXISTS選項使得刪除不存在的視圖時不拋出異常。

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'
update修改視圖
  • 由於違反了視圖中的WHERE birth_date < '1960-01-01'子句,因此拋出異常;
  • 利用with check option約束限制,保證更新視圖是在該視圖的權限範圍以內。

嵌套視圖:定義在另外一個視圖的上面的視圖

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:只檢查將要更新的視圖自己
 例如:對嵌套視圖不檢查其底層的視圖 
WITH 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 語言層面的代碼封裝與重用。

優勢

  • 存儲過程可封裝,並隱藏複雜的商業邏輯。
  • 存儲過程能夠回傳值,並能夠接受參數。
  • 存儲過程沒法使用 SELECT 指令來運行,由於它是子程序,與查看錶,數據表或用戶定義函數不一樣。
  • 存儲過程能夠用在數據檢驗,強制實行商業邏輯等。

缺點

  • 存儲過程,每每定製化於特定的數據庫上,由於支持的編程語言不一樣。當切換到其餘廠商的數據庫系統時,須要重寫原有的存儲過程。
  • 存儲過程的性能調校與撰寫,受限於各類數據庫系統。

一.建立存儲過程
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()

無參數存儲過程
無參數的存儲過程

對於存儲過程,能夠接收參數,其參數有三類:

  • in          僅用於傳入參數用
  • out        僅用於返回值用
  • inout     既能夠傳入又能夠看成返回值
-- 建立存儲過程
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 ;
1.結果集
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值
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 ;
3.事務
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 ;
4.遊標
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
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執行存儲過程
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」)。
NEW 與 OLD 詳解
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 會回滾事務,有:

  •  若是 BEFORE 觸發器執行失敗,SQL 沒法正確執行。
  •  SQL 執行失敗時,AFTER 型觸發器不會觸發。
  •  AFTER 類型的觸發器執行失敗,SQL 會回滾。

   4、索引                                                                          

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;
實驗1
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)
實驗2

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 ;
1.自定義函數
drop function func_name;
2.刪除函數
# 獲取返回值
declare @i VARCHAR(32);
select UPPER('alex') into @i;
SELECT @i;


# 在查詢中使用
select f1(11,nid) ,name from tb2;
3.執行函數
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:最低級別,以上狀況均沒法保證。(讀未提交)

安全性考慮: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';

說明:

  • username:你將建立的用戶名
  • host:指定該用戶在哪一個主機上能夠登錄,若是是本地用戶可用localhost,若是想讓該用戶能夠從任意遠程主機登錄,可使用通配符%
  • 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'@'%';

2. 受權:

命令:

GRANT privileges ON databasename.tablename TO 'username'@'host'

說明:

  • privileges:用戶的操做權限,如SELECTINSERTUPDATE等,若是要授予所的權限則使用ALL
  • databasename:數據庫名
  • tablename:表名,若是要授予該用戶對全部數據庫和表的相應操做權限則可用*表示,如*.*

例子:

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;

3.設置與更改用戶密碼

命令:

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()
pymysql
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
MysqlHelper

 

補充:數據庫優化方案

- 避免使用select * - 固定長度在前面- 內存代替表,如:性別等- 讀寫分離- 分庫- 分表 - 水平分表 - 垂直分表- 命中索引- 組合索引代替索引合併- 儘可能使用短索引- 若是取一條數據時,使用limit 1 select id,name from tb where name ='alex' limit 1;- 使用鏈接(JOIN)來代替子查詢(Sub-Queries)

相關文章
相關標籤/搜索