此次介紹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地址
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
表示可選的不重複的值date
以yyyy-mm-dd
形式存儲time
以hh:mm:ss
新式存儲year
以yyyy
新式存儲datetime
以yyyy-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
須要放在where
與order
之間, where
和order
能夠不存在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
A
和B
具備對等位置, 沒有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;複製代碼
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()複製代碼