此次介绍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()复制代码