Mysql 與 Pymysql

此次介紹mysql以及在python中如何用pymysql操做數據庫, 以及在mysql中存儲過程, 觸發器以及事務的實現, 對應到pymysql中應該如何操做.python


首先咱們在cmd窗口中展現常見的sql命令: mysql

  • 鏈接數據庫 mysql -u root -p

鏈接後顯示

  • 顯示數據庫 show databases;

顯示全部的數據庫

  • 建立數據庫, 設置默認編碼爲utf-8以及默認的排序方式 create database pymysql_db default charset utf8 collate utf8_general_ci;
  • 選擇用那個數據庫 use pymysql_db;
  • 顯示當前數據庫全部的表 show tables;

用戶操做以及用戶權限部分(不作演示, 不經常使用, 備查便可): linux

  • 建立用戶 create user 用戶名 @ ip地址 identified by 密碼;
  • 刪除用戶 drop user 用戶名 @ ip地址;
  • 用戶名修改 rename user 用戶名 @ ip地址 to 新用戶名@ip地址;
  • 修改指定用戶密碼 set password for 用戶名 @ ip地址 = Password(新密碼)
  • 查看權限 show grants for 用戶 @ ip地址
  • 給指定用戶增長權限 grant 權限 on 數據庫.表 to 用戶 @ ip地址
  • 取消指定用戶的權限 revoke 權限 on 數據庫.表 from 用戶 @ ip地址
  • 常見權限: 除grant外的全部權限 all privileges; 無訪問權限 usage; 查詢權限 select; 建立表權限 create; 刪除表內容權限 delete
  • 用戶 @ ip地址表示用戶在指定ip地址下才能訪問, 當ip地址%時候表示任意地址都可訪問(默認便是)

數據表的相關操做: sql

userinfo表建立以下: 數據庫

-- 建立一個名爲userinfo的表
CREATE TABLE `userinfo` (
    --     建立一個int類型的字段nid, 該字段不能爲空, 且自動遞增(注意: 一個表中只能容許一個自增的字段)
    `nid` INT (11) NOT NULL AUTO_INCREMENT,
    --     建立一個varchar類型的字段name, 默認爲空(varchar爲變長類型, 這裏指的是該字段最多佔32位, 可是查詢效率不如char定長類型)
    `name` VARCHAR (32) DEFAULT NULL,
    `color_nid` INT (11) DEFAULT NULL,
    --     指定nid爲主鍵(主鍵在一個表中是惟一不重複的, 此處可使用多個字段組合成主鍵, 只要組合不惟一便可, 主鍵默認會自動建立索引)
    PRIMARY KEY (`nid`),
    --   聲明一個名爲userinfo_ibfk_1的外鍵, 該外鍵由當前表中的color_nid與color表中的nid對應(說白了就是color_nid必須是color表中nid字段具備的值才行)
    CONSTRAINT `userinfo_ibfk_1` FOREIGN KEY (`color_nid`) REFERENCES `color` (`nid`)
--     指定當前數據庫的引擎爲INNODB, 默認字符集爲utf-8(INNODB可支持事務)
) ENGINE = INNODB DEFAULT CHARSET = utf8;複製代碼

color建立以下: ide

CREATE TABLE `color` (
  `nid` int(11) NOT NULL AUTO_INCREMENT,
  `tag` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;複製代碼
  • 刪除表(表結構以及表內容) drop table 表名
  • 刪除表內容(自增不會影響) delete from 表名
  • 刪除表內容(自增也清零) truncate table 表名
  • 修改表結構
    • 增長一列 alter table 表名 add 列名 類型
    • 刪除一列 alter table 表名 drop column 列名
    • 修改列類型 alter table 表名 modify column 列名 新類型;
    • 修改列名稱和列類型(類型保持不變也可) alter table 表名 change 原列名 新列名 類型;
  • 指定具體列爲主鍵 alter table 表名 add primary key(列名);
  • 刪除指定列的主鍵 alter table 表名 modify 列名 int, drop primary key;
  • 刪除當前表中全部列的主鍵 alter table 表名 drop primary key;
  • 爲當前表中列指定外鍵 alter table 從表(當前表) add constraint 外鍵名稱(形如:FK_從表_主表) foreign key 從表(外鍵字段) references 主表(主鍵字段);
  • 刪除外鍵 alter table 表名 drop foreign key 外鍵名稱
  • 修改默認值 alter table 表名 alter 列名 set default 新默認值;
  • 刪除默認值 alter table 表名 alter 列名 drop default;

mysql中字段的常見類型: 函數

  • 二進制位 bit(長度)
  • tinyint[(長度)] [有無符號unsigned] [位數低於長度時候是否填充零zerofill] 有符號表示範圍-128 ~ 127, 無負號表示範圍 0 ~ 255; 可用tinyint(1)來模擬boolean類型; 整型中的長度不作限制用, 僅僅作顯示用, 即長度大於位數時候是否選擇用零填充顯示
  • int[(長度)] [unsigned] [zerofill]
  • bigint[(長度)] [unsigned] [zerofill]
  • decimal[(數字總個數 [, 小數點個數])] [unsigned] [zerofill] 該類型會以字符串類型存儲在mysql, 以此來表示準確的浮點型
  • float[(數字總個數, 小數個數)] [unsigned] [zerofill]
  • double[(數字總個數, 小數個數)] [unsigned] [zerofill]
  • char(長度) 用固定長度存儲字符類型, 這裏的長度表示全部字符所佔長度, 最長爲255個字符
  • varchar(長度) 變長類型存儲字符類型, 這裏的長度表示人爲定製的最大長度, 查詢速度不如char定長類型
  • text 變長類型存儲大字符串, 最多2**16 − 1個字符
  • mediumtext 最多2**24 − 1個字符
  • longtext 最多2**32 − 1個字符
  • enum(v1 [,v2, v3]) 枚舉類型, v1表示可選的值
  • set(v1 [, v2, v3]) 集合類型, v1表示可選的不重複的值
  • dateyyyy-mm-dd形式存儲
  • timehh:mm:ss 新式存儲
  • yearyyyy新式存儲
  • datetimeyyyy-MM-dd hh:mm:ss 形式存儲

表中數據的操做 oop

  • 增長內容 insert into 表 (列名01,列名02...) values (值,值,值...) [,(值,值,值...)] 能夠一次增長多條數據
  • 刪除具體數據 delete from 表 where 條件'
  • 修改表中具體數據 update 表 set 列名= 值 where 條件
  • 查詢具體內容 select 列名01 as 別名 , 列名02 from 表 where 條件
  • 常見條件: 且關係and; 區間關係between 開始位置 and 結束位置; 在其中的關係in (v1, v2, v3); 不在其中的關係not in (v1, v2, v3); 在某種條件下in (select語句)
  • mysql中的兩種通配符: %匹配任意零個字符或者任意多個字符; _匹配任意一個
  • mysql中的限制條件: limit number 表前number行之內; limit start, number 表示從start行起始的number行之內; limit number offset start 表示從第start'開始的number行之內
  • mysql中排序顯示: order by 列1 desc,列2 asc 表示先以列1遞減排序, 若列1相同時候則以列2遞增排序
  • 分組: select count(列名),sum(列名),max(列名),min(列名) from 表 where 條件 group by 列名01,列名02 order by 列名 這裏的group by須要放在whereorder之間, whereorder能夠不存在
  • 連表查詢結果
    • select A.xx B.oo from A, B where A.x=B.o 沒有A.x=B.o對應的數據則不顯示任何結果
    • select A.xx B.oo from A inner join B where A.x=B.o AB具備對等位置, 沒有A.x=B.o對應的數據則不顯示任何結果
    • select A.xx B.oo from A left join B where A.x=B.o A表顯示全部, 對於B表若無符合A.x=B.o的數據則其值爲null來顯示
    • select A.xx B.oo from B right join A where A.x=B.o A表顯示全部, 對於B表若無符合A.x=B.o的數據則其值爲null來顯示
  • 組合不去重複顯示全部查詢結果 select 列名 from 表 union all select 列名 from 表
  • 組合去重顯示 select 列名 from 表 union select 列名 from 表

mysql中的視圖概念, 它並非一個真實存在的表,而是根據本身寫的sql語句執行所得的結果集, 方便查詢過程和結果比較複雜時候暫存結果以便它用. 使用視圖時候, 直接將它做爲表來使用便可 性能

  • 視圖建立
    -- 建立一個名爲vw1的視圖, 視圖內容爲select的語句執行結果
    CREATE VIEW vw1 AS
    SELECT
      userinfo.`name` AS uname, color.tag AS color
    FROM
      userinfo
    LEFT JOIN color ON userinfo.color_nid = color.nid複製代碼
  • 視圖使用 SELECT * from vw1;

執行結果

  • 刪除視圖 drop view vw1
  • 修改視圖
    -- 修改視圖vw1, 修改內容直接寫上現今要執行的sql語句便可
    ALTER VIEW vw1 AS
    SELECT
      userinfo.nid,userinfo.`name` AS uname, color.tag AS color
    FROM
      userinfo
    LEFT JOIN color ON userinfo.color_nid = color.nid複製代碼

在介紹觸發器, 存儲過程, 函數以及事務以前咱們先簡單過一下mysql中的條件和循環語句塊 fetch

  • 條件判斷
    if 條件 then
      普通sql語句;
    elseif 條件 then
       普通sql語句;
    else
       普通sql語句;
    end if;複製代碼
  • 循環語句
    • while循環
      while 條件 do
         普通sql語句;
      end while;複製代碼
    • repeat循環
      repeat
        普通sql語句;
        until 條件; 
      end repeat;複製代碼
    • loop循環
      loop_label: 標籤名
          普通sql語句;
          -- 繼續循環
          iterate loop_label;
          -- 跳出循環
          leave loop_label;
      end loop;複製代碼

觸發器是在對某個表執行操做(增長, 刪除和修改)的先後執行用戶特定的行爲, 好比對其餘的表執行增刪改的操做

  • 建立觸發器
    -- 定義結束符爲$, 在mac和linux中頗有必要
    delimiter $
    -- 若是存在tri_before_update_userinfo觸發器則刪除, 方便調試和修改
    DROP TRIGGER if EXISTS tri_before_update_userinfo $
    -- 建立tri_before_update_userinfo觸發器, 該觸發器會在更新userinfo表以前執行begin和end之間的內容(before表示以前, after表示以後)
    CREATE TRIGGER tri_before_update_userinfo BEFORE UPDATE ON userinfo FOR EACH ROW 
    BEGIN
      -- 若是在userinfo表中更改name爲tom的行則會在color表中插入一行(old表示原來的數據)
      IF old.name = 'tom' THEN
          INSERT INTO color(tag) VALUES('black');
      -- 若是在userinfo表中有name修改後爲cc則會在color表中插入一行(new表示修改後的數據)
      ELSEIF new.name = 'cc' THEN
          INSERT INTO color(tag) VALUES('yellow');
      END IF;
    end $
    delimiter ;複製代碼
  • 執行觸發器只須要修改userinfo表中的數據便可; 對於update操做既有old又有new關鍵字, 對於insert操做只有new關鍵字, 對於delete操做只有old關鍵字
  • 刪除指定觸發器 drop trigger if exists 觸發器名

存儲過程至關於一些sql語句的堆積, 可是sql語句執行後的結果集以及變量均可以返回給用戶; 而函數不能返回結果集, 僅僅是變量的操做

  • 建立存儲過程
    delimiter $
    DROP PROCEDURE IF EXISTS p1 $
    CREATE PROCEDURE p1(
    --     聲明僅用傳入參數用的整型形參
      in in_1 INT,
    --     聲明既能夠傳入又能夠當返回值的整型形參
      INOUT inout_1 int,
    --     聲明僅用作返回值的整型形參
      OUT out_1 INT 
    )
    BEGIN
    --     聲明語句塊中的臨時變量
      DECLARE tmp_in_1 INT;
      DECLARE tmp_inout_1 INT;
    --     賦值語句
      SET tmp_in_1 = in_1;
      set tmp_inout_1 = inout_1;
      SET out_1 = tmp_in_1 + tmp_inout_1;
    --     正常的sql查詢語句
      SELECT * from userinfo LIMIT in_1, inout_1;
    end $
    delimiter ;複製代碼
  • 使用存儲過程
    -- 設置用戶變量傳值,in類型可不用變量傳值, out類型不能傳入值, 
    -- set @in_1_tmp=1;
    set @inout_1_tmp=3;
    -- 調用存儲過程, 傳入參數
    CALL p1 (1,@inout_1_tmp,@out_1_tmp);
    -- 取得存儲過程的執行結果, 包括sql語句結果集以及變量值(in, inout以及out類型變量都能取得他們的值)
    SELECT @in_1,@inout_1_tmp,@out_1_tmp;複製代碼

執行結果-01

執行結果-02

  • 刪除存儲過程 drop procedure 存儲過程名

mysql中有許多對變量進行操做的內置函數, 同時咱們也能夠自定義函數

  • 內置函數第一部分
    SELECT
      CHAR_LENGTH("test") AS "字符串長度",
    --     拼接的任意一個參數爲null, 則拼接結果爲null
      CONCAT("C://", "workplace") AS "字符串拼接",
      CONCAT_WS("-","nick","tom") AS "自定義鏈接符拼接",
      CONV('c',16,10) AS "進制轉換",
      FORMAT(10000.00041,4) AS "格式化數字",
      INSERT("teach",1,2,'xxxx') AS "字符串替換"複製代碼

內置函數第一部分執行結果

  • 內置函數第二部分
    SELECT
      INSTR("mttm","tt") AS "字串位置",
      LEFT("hello, world",5) AS "從左截取字符串",
      LOWER("HELLO") AS "轉換小寫",
      UPPER("world") AS "轉換大寫",
      LTRIM("     test   ") AS "開始去空格",
      RTRIM("        now     ") AS "結尾去空格",複製代碼

內置函數第二部分執行結果

  • 內置函數第三部分
    SELECT
      LOCATE("tt","hehettlolo",2) AS "獲取子序列位置",
      REPEAT(" | roor",5) AS "重複字符串生成",
      REPLACE("hello","ll","ww") AS "字符串替換",
      REVERSE("123456") AS "字符串反轉",
      RIGHT("hello",3) AS "從右截取字符串",
      SUBSTRING("hello, test, world" FROM -11 FOR 4) AS "自定義截取字符串",
      SPACE(5) AS "返回空格字符串",
      TRIM("  test  ") AS "去除空格"複製代碼

內置函數第三部分執行結果

  • 建立函數
    delimiter $
    DROP FUNCTION IF EXISTS func1 $
    CREATE FUNCTION func1(
    --     定義整型形參
      i1 int,
      i2 int
    )
    -- 定義返回參數類型
    RETURNS INT
    BEGIN
      DECLARE tmp INT DEFAULT 0;
      SET tmp = i1 + i2;
      RETURN tmp;
    END $
    delimiter ;複製代碼
  • 使用自定義函數 SELECT func1(1,1);
  • 刪除自定義函數 DROP FUNCTION IF EXISTS 函數名;

事務的本質就是在存儲過程當中將多條sql語句做爲一個原子操做來執行, 其中之一未執行成功則直接回滾到原始狀態

  • 建立事務
    delimiter $
    CREATE PROCEDURE tp1(
    --     定義返回結果參數
      OUT num_flag_retunr INT
    )
    BEGIN
    --     sql執行發生異常時候, 返回值爲2, 並回滾到原始狀態
      DECLARE EXIT HANDLER FOR SQLEXCEPTION
      BEGIN
          SET num_flag_retunr=2;
          ROLLBACK;
      END;
    --     sql語言發生警告時候, 返回值爲1, 並回滾到原始狀態
      DECLARE EXIT HANDLER FOR SQLWARNING
      BEGIN
          SET num_flag_retunr=1;
          ROLLBACK;
      END;
    --     開始事務具體要執行的內容, 正確則提交執行結果不然執行上面的異常
      START TRANSACTION;
          DELETE FROM userinfo WHERE nid=4;
          INSERT INTO color(tag) VALUES("green");
      COMMIT;
      SET num_flag_retunr=0;
    END $
    delimiter ;複製代碼
  • 執行事務
    CALL tp1(@out_1);
    SELECT @out_1;複製代碼
  • 刪除事務 DROP PROCEDURE IF EXISTS 事務名

索引至關於爲咱們指定的列創建一個目錄, 根據目錄咱們能快速查找到所需數據

  • 索引種類
    • 普通索引 index : 僅僅加速查詢, 無約束
    • 惟一索引 unique : 加速查詢, 指定的列不能重複, 可出現一次null
    • 主鍵索引 primary key : 加速查詢, 列值惟一切不能爲null
    • 組合索引 : 多列做爲共同體組成索引, 效率高於多個索引列合併查詢
    • 全文索引: 數據庫存儲時候對存儲內容進行分詞存儲便於搜索查詢
  • 建立普通索引 CREATE INDEX name_index ON userinfo (name) 或者在建立表時候在表末尾加上 index 索引名 (列); 對於其餘索引也是相似
  • 刪除索引 drop 索引名 on 表名;
  • 查看當前表那些字段有索引 SHOW INDEX FROM userinfo;

有索引的字段顯示

  • 如下狀況即便建立了索引也不會使用索引:
    • %開頭的模糊匹配條件: select * from 表名 where 列名 like '%其餘';
    • 對創建索引的列使用函數查詢: select * from 表名 where 函數名(列名) = 其餘條件
    • 列類型匹配錯誤的條件查詢時候 : select * from 表名 where 列名 = 不正確的類型;
    • or條件中含有未創建索引的列時: select * from 表名 where 條件01 or 條件02';
    • 匹配條件爲不等於時候(主鍵例外) : select * from 表名 where 非主鍵列 != 其餘;
    • 匹配條件爲大於的時候(主鍵或索引爲整型例外) : select * from 表名 where 列名 > 其餘;
    • 排序時候選擇的映射與排序列不同即便都是索引列也不走索引(主鍵例外) : select 索引列-01 from 表名 order by 索引列-02 desc;
    • 組合索引爲 索引列-01索引列-02, 當先查索引列-02時候也不走索引
  • 用執行計劃能夠詳細顯示sql語句(使用查詢語句纔有意義)的執行狀況, 例如如執行EXPLAIN SELECT * from userinfo;

執行計劃執行結果

  • 關於上述表中詳細字段解釋 :
    • id 查詢順序標識, 表示sql查詢語句的執行順序
    • select_type 查詢語句的類型: 簡單查詢SIMPLE, 最外層查詢PRIMARY, 子查詢DERIVED, 映射是子查詢SUBQUERY, 聯合查詢UNION, 聯合查詢所得UNION RESULT
    • table 正在訪問的表名
    • partitions 分區類型
    • type 查詢方式, 查詢時間性能排序 : 全表掃描all > 全索引掃描index > 索引部分範圍內掃描range > 多單列索引合併掃描index_merge > 索引匹配一個或多個值掃描ref > 聯合主鍵索引或者惟一索引掃描eq_ref > 最多有一個匹配行優化後做爲常量表掃描const, 還有system特列, 性能與const近似
    • possible_keys 可能使用的索引
    • key 實際使用的索引
    • key_len 字節長度
    • rows 預測找到所需內容要查找的行數
    • extra 其餘信息, 多爲mysql解決查詢的詳細信息
  • limit分頁優化
    -- 查詢第1000條數據以後的10條數據
    -- 這種查詢方式會進行全文掃描
    SELECT * FROM userinfo LIMIT 1000,5;
    -- 這種方式僅僅優化了一點, 使用了一些普通索引和索引合併查詢
    EXPLAIN SELECT * FROM userinfo WHERE nid > (SELECT nid FROM userinfo LIMIT 1000, 1) LIMIT 5;
    -- 直接根據計算所得後的最大條數倒序排列查詢
    SELECT * FROM userinfo WHERE nid < 上次最大條數 ORDER BY nid DESC LIMIT 5;複製代碼
  • 慢查詢日誌能夠根據自定義設置記錄那些查詢性能查的sql語句 :
    • 查看全局變量 show global variables like "%名稱"
    • 設置全局變量 set global 變量名=值
    • 是否開啓慢日誌全局變量 slow_query_log = OFF
    • 時間限制全局變量 long_query_time = 2
    • 日誌文件存放位置全局變量 slow_query_log_file = /usr/slow.log
    • 是否記錄未使用索引的查詢語句全局變量 log_queries_not_using_indexes = OFF
  • 格式化查看慢日誌 mysqldumpslow [option] 日誌存放位置, 經常使用option以下:
    • 版本 -v或者--verbose
    • 調試模式 -d或者--debug
    • 排序方式 -s 規則選項, 默認是平均查詢時間at
    • 倒序排列顯示 -r
    • 顯示前number-t number
    • 不要將sql中數字轉換成N,字符串轉換成S, 選項爲, -a

python使用pymysql操做數據庫

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pymysql

# 建立鏈接通道, 設置鏈接ip, port, 用戶, 密碼以及所要鏈接的數據庫
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='pymysql_db')

# 建立遊標, 操做數據庫, 指定遊標返回內容爲字典類型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

# 調用存儲過程, 傳入參數
cursor.callproc('p1', (1, 5, 0))

# 獲得結果集1, 即sql語句執行結果
select_result = cursor.fetchone()
print(select_result)

# 執行存儲過程, 獲取返回值, @_存儲過程名_第一個參數
cursor.execute("select @_p1_0,@_p1_1,@_p_2")
select_result = cursor.fetchone()
print(select_result)

cursor.close()
conn.close()複製代碼

執行結果
相關文章
相關標籤/搜索