1 數據的介紹
-
概念:數據庫是一個用來存放數據的倉庫,是按照一定的數據結構來存儲、組織和管理數據。
-
分類方法:
-
關系型數據庫:Mysql(開源),Oracle(收費,銀行使用),SQL Server(收費),SQLite等
-
非關系型數據庫:redis,mongodb等
-
-
Python操作Mysql數據庫的幾種方式
-
MysqlDB
是早期python2.x時代所使用工具,但是由於現在已經進入python3.x時代,已經不再使用這個工具了。
-
mysqlclient
是mysqldb衍生版本,完全兼容mysqldb。
是django框架的orm映射工具
-
pymysql
是純python實現的驅動,也兼容mysqldb
也是我們重點學習的工具
-
sqlalchemy
是即支持原生SQL,也支持ORM的工具,類似於java的hibernate
-
2 數據庫的基本操作
1 pymysql的安裝
-
在線安裝:打開cmd輸入命令pip install pymysql
2 pymysql操作數據庫的流程
流程圖:
流程的文字描述:
1 導包
2 建立連接
3 獲取游標
4 執行SQL語句
5 關閉游標
6 關閉連接
3 案例數據准備
先啟動數據庫,我們使用phpstudy來啟動
如下圖所示,如果Mysql右邊的綠點是綠色的,那么就證明mysql啟動了
連接到數據庫
通過navicat工具來連接數據庫
打開navicat,然后新建連接
確認測試連接成功后,點擊確定(不是測試連接成功的確定,而是建立連接的確定)
連接到數據庫
然后打開數據庫,點擊頂部查詢
然后點擊下面的新建查詢
檢查有沒有運行成功的方式:
先關閉當前的數據庫連接,然后重新連接到數據庫
下面是sql語句:
CREATE DATABASE IF NOT EXISTS books default charset utf8;
USE books;
DROP TABLE IF EXISTS `t_book`;
CREATE TABLE `t_book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(20) NOT NULL COMMENT '圖書名稱',
`pub_date` date NOT NULL COMMENT '發布日期',
`read` int(11) NOT NULL DEFAULT '0' COMMENT '閱讀量',
`comment` int(11) NOT NULL DEFAULT '0' COMMENT '評論量',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '邏輯刪除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='圖書表';
INSERT INTO `t_book` VALUES ('1', '射雕英雄傳', '1980-05-01', '12', '34', '0');
INSERT INTO `t_book` VALUES ('2', '天龍八部', '1986-07-24', '36', '40', '0');
INSERT INTO `t_book` VALUES ('3', '笑傲江湖', '1995-12-24', '20', '80', '0');
DROP TABLE IF EXISTS `t_hero`;
CREATE TABLE `t_hero` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL COMMENT '姓名',
`gender` smallint(6) NOT NULL COMMENT '性別',
`description` varchar(200) DEFAULT NULL COMMENT '描述',
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '邏輯刪除',
`book_id` int(11) NOT NULL COMMENT '所屬圖書ID',
PRIMARY KEY (`id`),
KEY `t_hero_book_id` (`book_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='英雄人物表';
INSERT INTO `t_hero` VALUES ('1', '郭靖', '1', '降龍十八掌', '0', '1');
INSERT INTO `t_hero` VALUES ('2', '黃蓉', '0', '打狗棍法', '0', '1');
INSERT INTO `t_hero` VALUES ('3', '喬峰', '1', '降龍十八掌', '0', '2');
INSERT INTO `t_hero` VALUES ('4', '令狐沖', '1', '獨孤九劍', '0', '3');
INSERT INTO `t_hero` VALUES ('5', '任盈盈', '0', '彈琴', '0', '3');
4 數據庫基本操作
-
連接數據庫示例代碼
# 1 導包
# 注意如果導入的pymysql是黃色的,那么有可能你的項目名稱和python文件名稱是pymysql導致導包導入錯誤
# 如果是一個波浪線,有可能沒有選擇運行環境和沒有安裝pymysql
import pymysql
# 2 建立連接
conn = pymysql.connect(host='localhost', user='root', password='root', port=3306)
# 3 獲取游標
cursor = conn.cursor()
# 4 執行SQL語句:執行查詢數據庫版本的SQL語句
# 注意SQL語句當中的符號都必須是英文的符號
cursor.execute("select version();")
# 打印執行的結果
# 獲取執行結果
result = cursor.fetchone()
# 打印查詢結果
print("result=", result)
# 5 關閉游標
cursor.close()
# 6 關閉連接
conn.close()
-
數據庫查詢操作代碼
# 1 導包
import pymysql
# 2 建立連接:連接到數據庫(host:localhost username:root password:root database:books)
conn = pymysql.connect(host='localhost', user='root', password='root', database='books')
# 3 獲取游標
curcor = conn.cursor()
# 4 執行SQL語句:
# 查詢圖書表的數據(包括:圖書id、圖書名稱、閱讀量、評論量)
curcor.execute("select id,title,`read`,`comment` from t_book;")
# 獲取查詢結果的總記錄數:curcor.rowcount的意思是獲取執行SQL語句之后影響的行數
print("總記錄數:", curcor.rowcount)
# 獲取查詢結果的第一條數據
print("第一條數據:", curcor.fetchone())
# 獲取全部的查詢結果
# 注意:如果在上面先運行的cursor.fetchone()那么,數據的指針會下移,導致cursor.fetchall()獲取的數據
# 會缺少一行。要解決這個問題,需要重置指針。
print("執行了fetchone后的全部的查詢結果:", curcor.fetchall())
# 重置指針的方法:重新執行查詢語句
curcor.execute("select id,title,`read`,`comment` from t_book;")
# 重新之后再打印執行結果
book_list = curcor.fetchall()
print("重置指針之后的全部結果:", book_list)
# 遍歷book_list,打印所有的書
for book in book_list:
print("書:", book[1])
# 5 關閉游標
curcor.close()
# 6 關閉連接
conn.close()
-
插入語句
# 1 導包
import pymysql
# 2 建立連接
conn = pymysql.connect(host='localhost',
user='root',
password='root',
database='books',
autocommit=True)
# 3 獲取游標
cursor = conn.cursor()
# 4 執行SQL語句:執行插入一本的SQL語句
cursor.execute('insert into t_book(id, title, pub_date) values(4, "周易", "1986-01-01");')
# 查看執行結果
cursor.execute('select * from t_book;')
print("插入結果為:", cursor.fetchall())
# 5 關閉游標
cursor.close()
# 6 關閉連接
conn.close()
-
修改語句
# 導包
import pymysql
# 建立連接
conn = pymysql.connect(host='localhost', user='root', password='root', database='books', autocommit=True)
# 獲取游標
cursor = conn.cursor()
# 執行update語句:對周易這本書的閱讀量自增1操作
update_sql = "update t_book set `read`=`read`+1 where title='周易';"
cursor.execute(update_sql)
# 查詢周易這本書的閱讀量有沒有自增1
cursor.execute("select * from t_book where id =4;")
print("周易這本書:", cursor.fetchall())
# 關閉游標
cursor.close()
# 關閉連接
conn.close()
-
刪除語句
# 導包
import pymysql
# 建立連接
conn = pymysql.connect(host='localhost', user='root', password='root', database='books',autocommit=True)
# 獲取游標
cursor = conn.cursor()
# 刪除前的結果:
# 查看執行結果
cursor.execute("select * from t_book;")
print("刪除前的結果為:", cursor.fetchall())
# 執行刪除語句delete from t_book where id=4;
cursor.execute('delete from t_book where id=4;')
# 刪除后執行結果
cursor.execute("select * from t_book;")
print("刪除后的結果為:", cursor.fetchall())
# 關閉游標
cursor.close()
# 關閉連接
conn.close()
5 數據庫事務的概念
-
概念:事務是一組操作序列,這組操作序列,要么全部都成功,要么全部都失敗。
舉個例子:銀行轉賬的過程當中,所有的操作都要認為是一個事務,如果中間有一個操作失敗,那么之前成功操作都要回滾,(按照日志記錄回滾),保證操作沒有發生,還原原始的場景。
-
事務的特性(面試時偶爾會被問到)和作用
-
原子性:事務就像原子一樣不可分隔,事務的操作,要么完全的執行,要么完全的不執行。
-
一致性:是指提交事務前,數據都沒有改變,提交事務后,數據統一發生改變
-
隔離性:是指事務與事務之間,事務的中間狀態不對其他事務可見。
-
mysql數據庫如果是innodb引擎,那么他是基於事務來進行的操作,每一個連接都可以認為有事務在其中參與。
-
-
持久性:一旦提交事務成功之后,那么就會永久的修改數據庫中的數據,不會因為外部因素而發生改變,例如斷電不會影響數據。
-
作用:適用於一些要保證所有操作全部成功或全部失敗業務。(銀行轉賬案例)
-
-
操作事務的幾種方式:
-
自動提交事務的開關
1 建立連接時,通過連接中autocommit=True來開啟自動提交事務,默認是不開啟
2 建立連接之后,通過conn.autocommit(True)來開啟自動提交事務
-
手動提交事務和手動回滾事務
提交事務:conn.commit()
回滾:conn.rollback()
-
數據庫事務沒有提交和提交的案例案例演示:
# 1 導包
import pymysql
# 2 建立連接:為了演示手動提交事務,自動提交事務的開關需要使用的默認的false
conn = pymysql.connect(host='localhost', user='root', password='root', database='books', port=3306)
# 3 獲取游標
cursor = conn.cursor()
# 4 執行
# 需求:先新增一本書(t_book),然后再新增一個英雄人物(t_hero)
# 先新增一本書
cursor.execute('insert into t_book(id, title, pub_date) values(4,"本草綱目", "1980-01-01")')
# 再新增一個英雄人物
cursor.execute('insert into t_hero(id, gender,`name`, description, book_id) values(6,1, "李時珍", "醫學寶典", 4);')
# 最后查詢新增的書和人物
cursor.execute("select * from t_book where id=4;")
print("新增書為:", cursor.fetchall())
cursor.execute("select * from t_hero where id=6")
print("新增的人物為:", cursor.fetchall())
# 注意:如果沒有編寫提交事務的代碼,那么我們在代碼中插入的數據都不會生效,只會在當前的代碼的事務當中生效
# 如果想要在navicat當中查看到執行結果,我們需要手動提交事務(前提是自動提交事務的開關是false)
# 提交事務的代碼為:conn.commit()
conn.commit()
# 5 關閉游標
cursor.close()
# 6 關閉連接
conn.close()
回滾代碼案例
# 導包
import pymysql
# 建立連接
conn = pymysql.connect(host='localhost', user='root', password='root', database='books')
# 獲取游標
cursor = conn.cursor()
# 執行SQL語句
#新增一條圖書數據(id:4 title:西游記 pub_date:1986-01-01 )
#新增一條英雄人物數據(name:孫悟空 gender:1 book_id:4)
cursor.execute("insert into t_book(id, title, pub_date) values(6, '創新公司:皮克斯的啟示', '1970-01-01');")
cursor.execute("insert into t_hero(`name`, gender, book_id) values('喬布斯',1, 6);")
# 回滾事務的意思是:把當前事務中進行所有操作都撤銷。
# 為了演示回滾,首先在代碼中插入數據庫成功之后,查詢一次,理論上應該能夠查詢到我們插入的創新公司和喬布斯
cursor.execute("select * from t_book;")
print("查看當前代碼中的事務中,創新公司是否存在:", cursor.fetchall())
cursor.execute("select * from t_hero;")
print("查詢當前代碼中的事務中,喬布斯是否存在:", cursor.fetchall())
# 然后回滾后,由於當前的數據會被撤銷,所以再次查詢時,會查不到創新公司和喬布斯
conn.rollback()
# 回滾后再打印結果
cursor.execute("select * from t_book;")
print("查看回滾后當前代碼中的事務中,創新公司是否存在:", cursor.fetchall())
cursor.execute("select * from t_hero;")
print("查看回滾后當前代碼中的事務中,喬布斯是否存在:", cursor.fetchall())
# 關閉游標
cursor.close()
# 關閉連接
conn.close()
演示事務全部成功和全部失敗
在下面這個案例中,try語句中沒有出現異常,就會全部成功;如果出現了異常,就會全部回滾
# 導包
import pymysql
conn,cursor=None,None
try:
# 建立連接
conn = pymysql.connect(host='localhost', user='root', password='root', database='books')
# 獲取游標
cursor = conn.cursor()
# 執行SQL語句
# 需求:展示所有操作全部成功時,應該自動提交事務和操作中有一個事務失敗時,自動回滾事務
#新增一條圖書數據(id:4 title:西游記 pub_date:1986-01-01
#新增一條英雄人物數據(name:孫悟空 gender:1 book_id:4
print("Test--------------1")
cursor.execute("insert into t_book(id, title, pub_date) values(7,'創新公司:皮克斯的啟示222', '1970-01-01');")
cursor.execute("insert into t_hero(`name`, gender, book_id) values('喬布斯2',1, 6);")
print("Test--------------2")
# 回滾事務的意思是:把當前事務中進行所有操作都撤銷。
# 為了演示回滾,首先在代碼中插入數據庫成功之后,查詢一次,理論上應該能夠查詢到我們插入的創新公司和喬布斯
cursor.execute("select * from t_book;")
print("查看當前代碼中的事務中,創新公司是否存在:", cursor.fetchall())
cursor.execute("select * from t_hero;")
print("查詢當前代碼中的事務中,喬布斯是否存在:", cursor.fetchall())
print("Test--------------3")
# 這是主動加上的異常語句,如果要演示提交成功,可以把異常語句注釋掉
# 如果是不注釋:就是回滾
# 注釋:就是提交操作
raise Exception("主動拋出的異常")
# 提交事務
conn.commit()
except Exception as e:
print(e)
# 然后回滾后,由於當前的數據會被撤銷,所以再次查詢時,會查不到創新公司和喬布斯
if conn:
conn.rollback()
# 回滾后再打印結果
if cursor:
cursor.execute("select * from t_book;")
print("查看回滾后當前代碼中的事務中,創新公司是否存在:", cursor.fetchall())
if cursor:
cursor.execute("select * from t_hero;")
print("查看回滾后當前代碼中的事務中,喬布斯是否存在:", cursor.fetchall())
finally:
if cursor:
# 關閉游標
cursor.close()
if conn:
# 關閉連接
conn.close()