Python—MySQL


數據庫管理系統-DBMS(Database Management System)

     數據庫管理系統(DBMS) 是一種操縱和管理數據庫的大型軟件,用於建立、使用和維護數據庫,簡稱DBMS。
     它對數據庫進行統一的管理和控制,以保證數據庫的安全性和完整性。 用戶通過DBMS訪問數據庫中的數據,數據庫管理員也通過DBMS進行數據庫的維護工作。它可使多個應用程序和用戶用不同的方法在同時或不同時刻去建立,修改和詢問數據庫。
     種類:SqlServer, Oracle, sqlite, access, MySQL…


一、安裝MySQL

window:https://dev.mysql.com/downloads/mysql/

下載-解壓-加入環境變量

mysqld --initialize-insecure    # 初始化用戶 id:root 沒密碼

使用方法1(手動運行):

mysqld    # 運行服務端
mysql -u root -p    # 運行客戶端

使用方法2(默認開機運行mysql):

mysqld path --install    # 給windows安裝mysql服務
mysqld path --remove    # 給windows移除mysql服務
# 若已加入環境變量:
mysqld --install
mysqld --remove

# Install/Remove of the Service Denied! 如果出現這個錯誤以管理員身份打開命令提示符(win10:右鍵開始-A)

啓動/停止mysql服務:

net start mysql    # 在windows服務中啓動mysql
net stop mysql    # 在windows服務中停止mysql
# 或者在任務管理器中啓動/停止服務
# 如果報錯,請用管理員身份打開命令提示符

二、MySQL數據庫

1、概念

	數據庫: database
	表: table
	行

2、默認數據庫

	mysql: 用戶權限相關
	test: 用戶測試
	infomation_schema: MySQL本身構架相關

3、授權

用戶管理特殊命令

    創建用戶/修改密碼:

create user 'name'@'IP_address' identified by 'password';   # 創建用戶
drop user 'name'@'IP_address';    # 刪除用戶
rename user 'name'@'IP_address' to name@IP_address;    # 修改用戶
alter user 'name'@'ip_address' identified by password;    # 新版修改密碼
# set password for 'name'@'IP_address' = Password('new password');   # 舊版修改密碼

用戶登陸

mysql -u name -h 127.0.0.1 -p
# 輸入密碼
mysql -u root -p    # 沒有-h 默認爲localhost

賦予權限

show grants for 'name'@'IP'    # 查看權限
grant 權限 on 數據庫.表 to 'name'@'IP'    # 授權
revoke 權限 on 數據庫.表 from 'name'@'IP'    # 取消權限

"""
權限:
all privileges    除grant外的所有權限
usage             無訪問權限
alter             alter table
alter routine     alter procedure/drop procedure
create            create table
create routine    create procedure
create temporary  create temporary tables
create user       create user/drop user/rename user/revoke all privileges
create view       create view
delete            delete
drop              drop table
execute           call/存儲
file              select into oufile/load data infile
grant option      grant/revoke
index             index
insert            insert
lock tables       lock table
process           show full processlist
select            select
show databases    show databases
show view         show view
update            update
reload            flush
shutdown          mysqladmin shutdown
super             change master/kill/logs/purge/master/set global
replication client    服務器位置訪問
replication slave    
"""

授權中使用通配符

create user 'name'@'192.168.1.%' identified by 'password';    # 表示name在192.168.1.下所有子網都可以登陸

三、數據表基礎

1. 數據庫操作

show databases;              # 顯示所有數據庫名稱
create database db_name;     # 創建數據庫
create database db_name default charset utf8 collate utf8_general_ci;   # 創建數據庫設置編碼
use db_name;                 # 進入數據庫
drop database db_name;       # 刪除數據庫

2. 數據表操作

創建表

  1. \color{red}{表名}
  2. \color{red}{列名}
  3. \color{red}{類型}
'''數值:'''
# 整數
bit [(n)]	# 二進制位,n表示二進制位的長度(1-64),默認爲1
tinyint[(n)][unsigned][zerofill]	# 符號0 ~ 2^8-1
int [(n)] [unsigned] [zerofill]		# 有符號 -2^31 ~ 2^31-1, 無符號 0 ~ 2^32-1
bigint [(n)] [unsigned] [zerofill]  
# 小數
decimal		# 精確小數
	nid decimal(5, 10) # 保留10位小數,多出的四捨五入,少了用0補足
float:
double:
'''字符串:'''
# 定長
char	#
	# 長度以設置爲準,浪費空間,但是查詢速度相對較快
# 變長
varchar 
	# 節省空間,但是查找速度相對較慢
text
mediumtext
longtext
'''二進制數據:'''
TinyBlob、Blob、MediumBlob、LongBlob
	# 上傳文件
	# Blob, 強制二進制方式
	# varchar(65), "D:\program" 將上傳的文件保存到文件
	# 一般將文件路徑保存到數據庫,從數據庫中取到路徑操作文件
'''時間:'''
date
	# YYYY-MM-DD
time
	# HH:MM:SS
year
	# YYYY
datetime
	# YYYY-MM-DD HH:MM:SS
timestamp
	# YYYYMMDD HHMMSS
'''枚舉enum'''
Enum week:
	x = 1001
	y = 1002
	z = 1003
print(Enum.x)	# 1001

create table shirts(
					nid int primary key,
					size enum('small', 'medium', 'large') not null
);
	# insert 插入時size 列只能從enum中選擇一個
'''集合set'''
create table shirts(
			color set('blue', 'red', 'orange', 'green')
);
# insert插入時color列可以從set中選擇1或多個
  1. \color{red}{是否可以爲空}:NULL/not NULL
  2. \color{red}{默認值}:default 0
  3. \color{red}{自增列}:auto_increment (自增列必須是鍵-索引)
  4. engine=innodb\color{red}{engine=innodb}
  5. \color{red}{默認編碼}:default charset=utf8
 '創建表'     # 表名   列名 類型 是否可以爲空 自增列 主鍵
create table tb_name(nid int,
					name varchar(20));
create table tb_name(nid int NULL default 0, 
					 name varchar(20) not NULL, 
					sex varchar(20) not NULL)engine=innodb default charset=utf8;
'設置自增列' # 自增列數據會隨着數據插入自增,保證此列數據不重複
create table tb_name(nid int not NULL auto_increment primary key,
					 name varchar(20) NULL)engine=innodb default charset=utf8;
  1. ()\color{red}{主鍵-索引(加速查找)}:primary key(一張表只能有一個主鍵,唯一不能重複,not NULL, 一般情況將自增列設置爲主鍵)
        \color{red}{唯一列-約束}:數據唯一但是可以爲null
    \color{blue}{可以多列組合成唯一列或主鍵列}
create table tb_name(nid int not NULL auto_increment,
                     name varchar(20) NULL,
                     gender varchar(20),
                     primary key(nid, name)
)engine=innodb default charset=utf8;
  1. \color{red}{外鍵}:兩張表建立約束, 一對多
	# 創建表1 -- 學號 名字 年齡 班級id
create table student1(nid int not null auto_increment primary key,
                      name varchar(20) not null,
                      age int not null,
                      class_nid int not null)engine=innodb default charset=utf8;
# 創建表2 -- 班級id 班級名稱
create table class(nid int not null auto_increment primary key,
                    c_name varchar(20) not null)engine=innodb default charset=utf8;
'''創建表後添加表關聯'''
alter table student1 add constraint fk_s_c foreign key student1(class_nid) references class(c_name);
'''此時添加表1數據中class_nid如果沒有在表2中的nid,語句會報錯'''


'''創建表時直接建立關聯'''
# 先創建表1 -- 班級id 班級名稱(代碼如上)
# 創建表2
create table student1(nid int not NULL primary key,
                    name varchar(20) not null,
                    age int not null,
                    class_nid int not null,
                    constraint fk_s_c foreign key (class_nid) references class(nid)
)engine=innodb default charset=utf8;

表操作

show tables;             # 顯示所有表
desc tb_name;            # 顯示錶描述
drop table tb_name;      # 刪除表
delete from tb_name;     # 清空表內容
truncate table tb1;      # 清空表內容,自增回到原點
select * from tb_name;   # 查看錶內容
'''修改列'''
alter table 表名 add 列名 類型;                # 添加列
alter table 表名 drop column 列名;             # 刪除列
alter table 表名 modify column 列名 類型;      # 修改類型
alter table 表名 change 原列名 新列名 類型;     # 修改列名和類型
'''修改主鍵'''
alter table 表名 add primary key(*列名);        # 添加主鍵
alter table 表名 drop primary key;              # 刪除主鍵
alter table 表名 modify 列名 int, drop primary key;    # 刪除主鍵
'''修改外鍵'''
alter table 從表 add constraint fk_1_2 foreign key 從表(字段) references 主表(字段);
alter table 表名 drop foreign key 外鍵名稱;
'''修改默認值'''
alter table 表名 alter 列名 set default 1000;
alter table 表名 alter 列名 drop default;

3. 數據行操作

insert into tb_name(name, age) values('wolf', 25);
# 增加多行
insert into tb_name(name, age) values('wolf', 25), ('name2', 18), ('name3', 20);
# 從一個表複製到另外一個表
insert into 表1(列,列,列) select 列,列,列 from 表2		# 兩個表對應列必須數據類型一樣或者可轉換

delete from 表 where 列=value;
delete from 表 where nid>3;
> < = != and or

udpate 表 set name='wolfx',age=22 where name='wolf' and age>25;

select * from;
select * from 表 where nid>5;
select nid, name from;

其它*

1. 條件

select * from 表 where nid > 4 and name != 'wolf' and age > 18;
							    age not in (27, 28, 29);
							    age in ( 12, 15, 18);
							    age in (select age from);
							    age between 21 and 29;

2. 通配符 -模糊匹配

select * from 表 where name like 'wolf%';	# 以wolf開頭的多個字符
								 '%lf_'; 	# 以wolf開頭的一個字符

3. 分頁

select * from 表 limit 7;		# 表前7行
					   7, 11;	# 表7 ~ 18行, 從第7行開始的11行
					   11 offset 7;	# 表7 ~ 18行

4. 排序

select * from 表 order by nid asc;	# 按nid排序,順序
							  desc  # 按nid排序,逆序
select * from 表 order by nid asc, name desc;	# 先按nid順序,相同的再按name逆序

5. 分組

# 按nid分組
select nid from 表 group by nid;	
# 按名字分組後取出最高成績
select name, max(score) from 表 group by name;	
# 按名字分組後計算總成績,最低分數,計數各id數量,並給表頭重命名
select name, sum(score) as a_score, count(id) as c_id, min(score) from 表 group by name;	
# 對於使用聚合條件取到的數據,要使用having進行匹配,不能用where
select name, sum(score) as a_score from 表 group by name having a_score > 650;	

6. 組合

select nid from1 union select nid from2;	# union 聯合顯示2張表的數據,默認去重
select nid from1 union all select nid from2;	# union all 不去重

7. 連表**

select * from1,2;		# 將表2所有數據與表1每行數據對應顯示
select * from1,2 where 表1.=2.;	# 顯示錶1某列與表2某列對應相等時的數據
select * from1 left join 表2 on 表1.=2.;		# 主表在前
# 可以連接多個表
select * from1 left join 表2 on 表1.=2.列 
left join 表3 on 表1.=3.列 
left join 表4 on 表2.=4.;
select * from2 inner join 表1 on 表1.=2.;	# 在left join基礎上去掉Null數據
# 優先用left join ,效率更高

8. 臨時表**

select 表1.nid, tb2.name from (select nid from2) as tb2 left join 表3 on 表1.nid > 18;

9. 去重distinct

# 查詢哪些學生有得分記錄,可能有多門選課,去掉重複項
select distinct student_id from score;

10. avg

# 計算分組之後某列數據各組的平均值
select avg(num) from score group by student_id having avg(num)>60;

11. 試圖view

# 將臨時表創建爲試圖,下次調用時直接調用v_name作爲臨時表名字即可,mysql會自動解析v_name的sql語句
create view v_name as 
	select 表1.,2.from1 left join 表2 on 表1.=2.;
# 直接調用v_name
select v_name.from v_name;

12. 存儲過程

# 存儲過程(寫在客戶端,類似一個函數,在客戶端中直接調用)
delimiter //		# 將;終止符修改爲//
create procedure p_name()
begin
	select * from;
end //
delimiter;		# 將//終止符改回;

# 取出存儲結果
call p_name()

4. 報錯處理

ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'xxxxx' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

翻譯:錯誤1055(42000):選擇列表的表達式#2不在GROUP BY子句中,並且包含非聚合列‘xxxxxx’,該列在功能上不依賴於GROUP BY子句中的列;這與sql_mode=only_full_group_by不兼容

意思是:select\color{red}select中選擇顯示的列名必須有出現在group\color{red}group by\color{red}by後面的


四、Python中使用pymysql

1. 安裝pymysql

pip install pymysql

pymysql: 專門用來操作MySQL的python模塊

2. 操作

import pymysql


# 創建連接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='test', charset='utf8')
# 創建遊標
# cursor = conn.cursor()	# 查看數據時獲取到的數據爲元組
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)		# 取數據時將數據改爲字典形式
# 執行SQL,並返回影響行數
effected_row = cursor.execute('insert into table values('xxx', xxx)')
# 提交操作
conn.commit()

new_nid = cursor.lastrowid		# 獲取最新的一條自增列數據
print(new_nid)

# 關閉遊標
cursor.close()
# 關閉連接
conn.close()

3. 注意事項*

  1. 一種錯誤的插入字符串的方式:
import pymysql


# 創建連接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='test', charset='utf8')
# 創建遊標
cursor = conn.cursor()	

data = input('請輸入成績:')
sql = 'insert into table(name) values('%s')'%data
# 執行SQL,並返回影響行數
effected_row = cursor.execute(sql)

# 提交操作
conn.commit()
# 關閉遊標
cursor.close()
# 關閉連接
conn.close()

以上操作會造成SQL\color{orange}SQL注入,是使\color{red}絕對不能使用的。

\color{blue}別人可能不需要密碼就能登陸數據庫,並獲取數據庫內容


'''用戶登陸'''

import pymysql


# 創建連接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='test', charset='utf8')
# 創建遊標
cursor = conn.cursor()

SQL\color{orange}SQL注入:

sql = "select * from table where user_id='%s' and pwd='%s'"	# 可以取到數據

# 執行SQL,並返回影響行數
effected_row = cursor.execute(sql)

user_id = "xxx' or 1=1 --"
pwd = '000'
sql = sql%(user_id, pwd)
sql = "select * from table where user_id='xxx' or 1=1 --' and pwd='000'"	
# -- 在mysql中爲註釋語句,會註釋後面的條件,1=1爲已成立條件
'''輸入數據時,在數據中加入絕對成立的條件,和註釋符號 -- ,會改變sql語句,從而導致數據庫侵入'''

# 提交操作
conn.commit()
# 關閉遊標
cursor.close()
# 關閉連接
conn.close()
  1. 正確的參數傳遞方式:
data = input('請輸入成績:')
# 執行SQL,並返回影響行數
effected_row = cursor.execute('insert into table(name) values(%s)', data)
# 多條參數
effected_row1 = cursor.execute('insert into table(nid, name, age) values(%s, %s, %s)', (1, 'wolf', 25))
# 多列參數
list1 = [(2, 'Peter', 22), 
(3, 'Michale', 21), 
(4, 'Lion', 23)]
effected_row1 = cursor.executemany('insert into table(nid, name, age) values(%s, %s, %s)', list1)

其餘SQL操作替換掉SQL語句即可

  1. 查看數據表內容
data = cursor.execute('select * from table')

# res = data.fetchone()		# 取第一條數據
# res = data.fetchmany(4)	# 取4條數據,以一個元組輸出,即使是一條數據
res = data.fetchall()
'''取數據時會移動指針'''
print(res)

# 移動指針
cursor.scroll(0, mode='abssolute')	# 指針直接回到多少行,絕對
cursor.scroll(1, mode='relative')	# 指針向下走一行,相對
cursor.scroll(-1, mode='relative')	# 指針向上走一行,相對
''' '''
'''查看數據不需要提交操作'''
# conn.commit()
# 關閉遊標
cursor.close()
# 關閉連接
conn.close()

4.Pymysql中執行存儲過程

# 執行存儲過程 (客戶端)
coursor.callproc('p_name')
# 取出數據
res = cursor.fetchall()
print(res)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章