1. MySQL的基本操作
1.1 介紹
- 數(shù)據(jù)添加
INSERT
語法猜欺、INSERT
方言語法涧黄、INSERT
子查詢、IGNORE
關(guān)鍵字春宣。 - 數(shù)據(jù)修改
UPDATE
語法、UPDATE
表連接 - 數(shù)據(jù)刪除
DELETE
語法、DELETE
表連接
1.2 數(shù)據(jù)插入操作
-
INSERT
語句
INSERT
語句可以向數(shù)據(jù)表寫入記錄簸搞,可以是一條記錄,也可以是多條記錄。
INSERT INTO 表名(字段1,字段2, ...) VALUES(值1,值2,...);
INSERT INTO 表名(字段1,字段2, ...) VALUES(值1,值2,...), (值1,值2,...);
例如:向部門表插入新的部門
INSERT INTO t_dept(deptno, dname, loc)
VALUES(50, "技術(shù)部", "北京");
INSERT INTO t_dept(deptno, dname, loc)
VALUES(60, "后勤部", "北京"), (70, "保安部", "北京");
注意:不聲明字段名稱也可以寫入數(shù)據(jù)沽讹,不過會(huì)降低寫入效率。
-
INSERT
插入字段可以有子查詢,但子查詢的結(jié)果必須是單行記錄乘盖,并且子查詢返回的字段必須只有一個(gè)。
例如:向技術(shù)部添加一名員工記錄
INSERT INTO t_emp
(empno, ename, job, mgr, hiredate, sal, comm, deptno)
VALUES(8081, "劉娜", "SALESMAN", 8000, "1988-12-21", 2000, NULL,
(SELECT deptno FROM t_dept WHERE dname = "技術(shù)部"));
-
INSERT
語句方言
方言:只能在MySQL
數(shù)據(jù)庫上執(zhí)行的SQL
語法,不具備通用性衩侥。
INSERT [INTO] 表名 SET 字段1=值1, 字段2=值2, ...;
其中,INTO
關(guān)鍵字可以省略峦萎。
INSERT INTO t_emp
SET empno=8002, ename="Jake", job="SALESMAN", mgr=8000,
hiredate="1985-12-21",sal=2500,comm=NULL, deptno=50;
-
IGNORE
關(guān)鍵字
插入多條數(shù)據(jù)時(shí)雄卷,如果與現(xiàn)有的記錄產(chǎn)生主鍵沖突或唯一值沖突,寫入報(bào)錯(cuò)揣钦,導(dǎo)致一條記錄也寫不進(jìn)去。使用IGNORE
關(guān)鍵字會(huì)讓INSERT
忽略沖突的數(shù)據(jù),只插入沒有沖突的數(shù)據(jù)。
INSERT [IGNORE] INTO 表名 ...;
INSERT INTO t_dept(deptno, dname, loc)
VALUES(60, "A", "北京"), (80, "B", "上海");
-- 1062 - Duplicate entry '60' for key 'PRIMARY', Time: 0.012000s
INSERT IGNORE INTO t_dept(deptno, dname, loc)
VALUES(60, "A", "北京"), (80, "B", "上海");
-- Affected rows: 1, Time: 0.036000s
1.3 數(shù)據(jù)更新操作
-
UPDATE
語句
UPDATE [IGNORE] 表名 SET 字段1=值1, 字段2=值2,...
[WHERE 條件1 ...] [ORDER BY ...] [LIMIT ...];
注意:UPDATE
中的LIMIT
子句只能寫一個(gè)參數(shù)LIMIT N
鸽扁。不可以寫LIMIT N M
巩那。 - 數(shù)據(jù)更新練習(xí)
(1) 把每個(gè)員工的編號(hào)和上司的編號(hào)+1
,使用ORDER BY
子句完成
UPDATE t_emp
SET empno=empno+1, mgr=mgr+1
ORDER BY empno DESC;
注意:需要使用ORDER BY
子句降序,否則在+1
的時(shí)候可能發(fā)生主鍵沖突。
(2) 把月收入前3
名的員工底薪減100
元璃吧,用LIMIT
子句完成
UPDATE t_emp
SET sal = sal - 100
ORDER BY sal + IFNULL(comm,0) DESC
LIMIT 3;
(3) 把10
部門中巴元,工齡超過20
年的員工修己,底薪增加200
戴涝。
UPDATE t_emp
SET sal = sal + 200
WHERE deptno = 10 AND DATEDIFF(NOW(),hiredate) / 365 > 20;
-
UPDATE
語句的表連接
例如:把ALLEN
調(diào)往RESEARCH
部門奸鸯,職務(wù)調(diào)整為ANALYST
(1) 相關(guān)子查詢寫法,效率非常低扬虚。
UPDATE t_emp
SET deptno = (SELECT deptno FROM t_dept WHERE dname = 'RESEARCH'),
job = 'ANALYST'
WHERE ename = 'ALLEN';
(2) 使用表連接來改造UPDATE
語句
語法1:UPDATE 表1 JOIN 表2 ON 條件 SET 字段1=值1, 字段2=值2, ...;
語法2:UPDATE 表1, 表2 WHERE 條件 SET 字段1=值1, 字段2=值2, ...;
表連接的UPDATE
語句可以修改多張表的記錄。
UPDATE t_emp e
JOIN t_dept d
SET e.deptno = d.deptno, e.job = 'ANALYST', d.loc='北京'
WHERE e.ename = 'ALLEN' AND d.dname = 'RESEARCH';
注釋:①JOIN
表連接并沒有寫ON
連接條件。②同時(shí)修改了兩張表的數(shù)據(jù)。
- 數(shù)據(jù)更新和數(shù)據(jù)刪除時(shí)不推薦使用子查詢的原因
(1) 子查詢效率低
(2) 不允許對(duì)要更新或刪除的數(shù)據(jù)做子查詢 - 把底薪低于公司平均底薪的員工坎匿,帶薪增加
150
元
UPDATE t_emp e1
JOIN (SELECT AVG(sal) avg FROM t_emp) s
ON e1.sal < s.avg
SET e1.sal = e1.sal + 150;
-
UPDATE
語句的表連接既可以是內(nèi)連接侥锦,又可以是外連接
例如:把沒有部門的員工,或者SALES
部門低于2000
元底薪的員工,都調(diào)到20
部門玄柏。
UPDATE t_emp e
LEFT JOIN t_dept d
ON e.deptno = d.deptno
SET e.deptno = 20
WHERE e.deptno IS NULL OR (d.dname = 'SALES' AND e.sal < 2000);
注釋:① 判斷是否是NULL
-IS NULL
绍坝。② 如果不使用LEFT JOIN
椎咧,則取不到?jīng)]有部門的員工蟋座。
1.4 數(shù)據(jù)刪除
-
DELETE
語句用于刪除記錄
DELETE [IGNORE] FROM 表名 [WHERE 條件1, 條件2...] [ORDER BY ...] [LIMIT ...];
子句執(zhí)行順序:FROM > WHERE > ORDER BY > LIMIT > DELETE
-
DELETE
語句練習(xí)
(1) 刪除10
部門中莫矗,工齡超過20
年的員工記錄
DELETE FROM t_emp
WHERE deptno = 10 AND DATEDIFF(NOW(),hiredate) / 365 >= 20;
(2) 刪除20
部門中工資最高的員工記錄
DELETE FROM t_emp
WHERE deptno = 20
ORDER BY sal + IFNULL(comm,0) DESC
LIMIT 1;
-
DELETE
語句的表連接
WHERE
語句中寫子查詢的效率很低三娩,我們可以使用表連接改造DELETE
語句眨唬。
DELETE 表1, ... FROM 表1 JOIN 表2 ON 條件
[WHERE 條件1, 條件2...] [ORDER BY ...] [LIMIT ...];
-
DELETE
語句表連接聯(lián)系
(1) 刪除SALES
部門和該部門的全體員工記錄
DELETE e, d FROM t_emp e JOIN t_dept d
ON e.deptno = d.deptno
WHERE d.dname = 'SALES';
(2) 刪除每個(gè)低于部門平均底薪的員工記錄
DELETE e FROM t_emp e
JOIN (SELECT deptno, AVG(sal) sal FROM t_emp GROUP BY deptno) g
ON e.deptno = g.deptno
WHERE e.sal < g.sal;
(3) 刪除員工KING
和他直接下屬的員工記錄瓦宜,用表連接實(shí)現(xiàn)
-- 表連接寫法1
DELETE e1, e2 FROM t_emp e1 JOIN t_emp e2
ON e1.ename = 'KING' AND e1.empno = e2.mgr;
--表連接寫法2
DELETE e1 FROM t_emp e1
JOIN (SELECT empno FROM t_emp WHERE ename = 'KING') e2
ON e1.mgr = e2.empno OR e1.ename = 'KING';
-
DELETE
語句的表連接既可以是內(nèi)連接昵慌,又可以是外連接
例如:刪除SALES
部門的員工以及沒有部門的員工
DELETE e FROM t_emp e
LEFT JOIN t_dept d
ON e.deptno = d.deptno
WHERE d.dname = 'SALES' OR e.deptno IS NULL;
- 快速清空數(shù)據(jù)表中所有記錄
DELETE
語句是在事務(wù)機(jī)制下刪除記錄已卷,刪除記錄之前鹉梨,先把將要?jiǎng)h除的記錄保存到日志文件里析桥,然后再刪除記錄埋虹。
TRUNCATE
語句在事務(wù)機(jī)制之外刪除記錄截亦,速度遠(yuǎn)超DELETE
語句却桶。
語法:TRUNCATE TABLE 表名;
TRUNCATE TABLE t_emp;
1.5 總結(jié)
- 技能清單
掌握INSERT
語法
掌握UPDATE
語法
掌握DELETE
語法
掌握數(shù)據(jù)更新和刪除中的表連接語法 - 知識(shí)體系
初識(shí)數(shù)據(jù)庫:MySQL
安裝與使用
DDL
階段:管理數(shù)據(jù)庫與數(shù)據(jù)表
DML
階段:數(shù)據(jù)的增刪改查
2. MySQL基本函數(shù)的使用
2.1 介紹
- 學(xué)習(xí)目標(biāo)
(1) 數(shù)字函數(shù)
FORMAT
颖系、ABS
嗅剖、MOD
、CEIL
嘁扼、FLOOR
信粮、ROUND
趁啸、EXP
...
(2) 字符函數(shù)
UPPER
强缘、LOWER
、CHAR_LRNGTH
莲绰、CONCAT
、INSTR
...
(3) 日期函數(shù)&
條件函數(shù)
NOW
姑丑、DATE_FORMAT
蛤签、DATE_ADD
、DATEDIFF
栅哀、IF
震肮、IFNULL
...
2.2 MySQL基本函數(shù)
-
MySQL
的函數(shù)
數(shù)字函數(shù)、字符函數(shù)留拾、日期函數(shù)戳晌、條件函數(shù) - 數(shù)字函數(shù)
函數(shù) | 功能 | 用例 |
---|---|---|
ABS |
絕對(duì)值 | ABS(-100) |
ROUND |
四舍五入 | ROUND(4.62) |
FLOOR |
向下取整 | FLOOR(9.9) |
CEIL |
向上取整 | CEIL(3.2) |
POWER |
冪函數(shù) | POWER(2,3) |
LOG |
對(duì)數(shù)函數(shù) | LOG(7, 3) |
LN |
求對(duì)數(shù)函數(shù)(以e 為底數(shù)) |
LN(10) |
SELECT ABS(-100); # 100
SELECT ROUND(4.6288 * 100) / 100; # 4.6300
SELECT FLOOR(9.9); # 9
SELECT CEIL(3.2); # 4
SELECT POWER(2, 3); # 8
SELECT LOG(7, 3); # 0.5645750340535797
SELECT LN(10); # 2.302585092994046
函數(shù) | 功能 | 用例 |
---|---|---|
SQRT |
開平方 | SQRT(9) |
PI |
圓周率 | PI() |
SIN |
正弦 | SIN(1) |
COS |
余弦 | COS(1) |
TAN |
正切 | TAN(1) |
COT |
余切 | COT(1) |
RADIANS |
角度轉(zhuǎn)換弧度 | RADIANS(30) |
DEGREES |
弧度轉(zhuǎn)換角度 | DEGREES(1) |
SELECT SQRT(9); # 3
SELECT PI(); # 3.141593
SELECT SIN(RADIANS(30)); # 0.49999999999999994
SELECT COS(RADIANS(45)); # 0.7071067811865476
SELECT TAN(RADIANS(35)); # 0.7002075382097097
SELECT COT(RADIANS(45)); # 1.0000000000000002
SELECT DEGREES(1); # 57.29577951308232
- 獲取系統(tǒng)時(shí)間函數(shù)
NOW()
- 獲取當(dāng)前系統(tǒng)日期和時(shí)間,格式為yyyy-MM-dd hh:mm:ss
CURDATE()
- 獲取當(dāng)前系統(tǒng)日期痴柔,格式為yyyy-MM-dd
CURTIME()
- 獲取當(dāng)前系統(tǒng)時(shí)間沦偎,格式為hh:mm:ss
SELECT NOW(), CURDATE(), CURTIME();
2020-01-01 10:59:43 2020-01-01 10:59:43
- 日期格式化函數(shù)
DATE_FORMAT()
- 用于格式化日期
占位符 | 作用 | 占位符 | 作用 |
---|---|---|---|
%Y |
年份 | %m |
月份 |
%d |
日期 | %w |
星期(數(shù)字) |
%W |
星期(名稱) | %j |
本年第幾天 |
%U |
本年第幾周 | %H |
小時(shí)(24 ) |
%h |
小時(shí)(12 ) |
%i |
分鐘 |
%s |
秒 | %r |
時(shí)間(24 ) |
%T |
時(shí)間(12)
|
-- 查詢明天你的生日是星期幾。
SELECT DATE_FORMAT('2020-04-05', '%w - %W') #0 - Sunday
-- 查詢1981年上半年入職的員工有多少人
SELECT COUNT(*) FROM t_emp
WHERE DATE_FORMAT(hiredate, "%Y") = 1981
AND DATE_FORMAT(hiredate, "%m") <=6; # 5
注釋:數(shù)據(jù)庫中支持的最小的時(shí)間單位是秒,而不是毫秒豪嚎。
- 日期偏移計(jì)算
DATE_ADD()
- 可以實(shí)現(xiàn)日期偏移計(jì)算搔驼。
格式:DATE_ADD(日期, INTERVAL 偏移量 時(shí)間單位)
SELECT
NOW(),
DATE_ADD(NOW(),INTERVAL 15 DAY) d1,
DATE_ADD(NOW(),INTERVAL -300 MINUTE) d2,
DATE_ADD(DATE_ADD(NOW(), INTERVAL -2 MONTH), INTERVAL -3 DAY) d3;
# 2020-01-01 11:31:28 2020-01-16 11:31:28 2020-01-01 06:31:28 2019-10-29 11:31:28
注釋:在MySQL
數(shù)據(jù)庫中,兩個(gè)日期不能直接加減侈询,日期也不能與數(shù)字加減舌涨。
- 日期差值
DATEDIFF()
- 計(jì)算兩個(gè)日期之間相差的天數(shù)。
SELECT DATEDIFF(NOW(),DATE_ADD(NOW(),INTERVAL -1 MONTH)); # 31
- 字符函數(shù)
函數(shù) | 功能 | 用例 |
---|---|---|
LOWER |
轉(zhuǎn)換為小寫 | LOWER(ename) |
UPPER |
轉(zhuǎn)換為大寫 | UPPER(ename) |
LENGTH |
字符數(shù)量 | LENGTH(ename) |
CONCAT |
連接字符串 | CONCAT(sal, "$") |
INSTR |
字符出現(xiàn)的位置 | INSTR(ename, "A") |
INSERT |
插入/替換字符串 | INSERT("你好", 1, 0, "先生") |
REPLACE |
替換字符 | REPLACE("你好先生", "先生", "女士") |
SELECT LOWER(ename), UPPER(ename), LENGTH(ename),
CONCAT(sal, '$'), INSTR(ename,'A') FROM t_emp;
-- ...
-- allen ALLEN 5 1600.00$ 1
SELECT INSERT('你好', 1, 0, '先生'); # 先生你好
SELECT INSERT('你好', 1, 1, '先生'); # 先生好
SELECT REPLACE('你好先生', '先生', '女士'); # 你好女士
函數(shù) | 功能 | 用例 |
---|---|---|
SUNSTR |
截取字符串 | SUNSTR('你好世界', 3, 4) |
SUNSTRING |
截取字符串 | SUNSTRING('你好世界', 3, 2) |
LPAD |
左側(cè)填充字符 | LPAD('Hello', 10, '*') |
RPAD |
右側(cè)填充字符 | RPAD('Hello', 10, '*') |
TRIM |
去除首尾空格 | TRIM(' 你好先生 ') |
SELECT SUBSTR('你還世界',3, 4); # 世界
SELECT SUBSTRING('你好世界', 3, 2); # 世界
SELECT LPAD(SUBSTRING('12345678901',8,4),11,'*'); # *******8901
SELECT RPAD(SUBSTRING('李曉娜', 1, 1),LENGTH('李曉娜') / 3,'*'); # 李**
SELECT TRIM(' Hello World! ') #Hello World!
- 條件函數(shù)
SQL
語句中可以利用條件函數(shù)來實(shí)現(xiàn)編程語言里的條件判斷扔字。
IFNULL(表達(dá)式, 值)
IF(表達(dá)式, 值1, 值2)
例如:中秋節(jié)公司員工發(fā)放禮品囊嘉,SALES
部門發(fā)放禮品A
, 其余部門發(fā)放禮品B
, 打印每個(gè)員工獲得的禮品。
SELECT e.ename, d.dname, IF(d.dname = 'SALES', '禮品A', '禮品B')
FROM t_emp e
JOIN t_dept d
ON e.deptno = d.deptno;
- 復(fù)雜條件判斷
公司年慶決定組織員工集體旅游革为,每個(gè)部門旅游目的地不同扭粱。SALES
部門去P1
地點(diǎn),ACCOUNTING
部門去P2
地點(diǎn)篷角,RESEARCH
部門去P3
地點(diǎn)焊刹,查詢每名員工的旅行地點(diǎn)。
SELECT
e.ename, d.dname,
CASE d.dname
WHEN 'SALES' THEN 'P1'
WHEN 'ACCOUNTING' THEN 'P2'
WHEN 'RESEARCH' THEN 'P3'
END AS place
FROM t_emp e
JOIN t_dept d
ON e.deptno = d.deptno
- 薪資調(diào)整方案
(1)SALES
部門中工齡超過20
年恳蹲,漲10%
虐块。
(2)SALES
部門中工齡不滿20
年,漲5%
嘉蕾。
(3)ACCOUNTING
部門贺奠,漲300
。
(4)RESEARCH
部門里低于部門平均底薪错忱,漲200
儡率。
(5) 沒有部門的員工,漲100
以清。
UPDATE t_emp e LEFT JOIN t_dept d ON e.deptno = d.deptno
LEFT JOIN (SELECT deptno, AVG(sal) avg FROM t_emp GROUP BY deptno) g
ON e.deptno = g.deptno
SET e.sal = (
CASE
WHEN d.dname = 'SALES' AND DATEDIFF(NOW(),e.hiredate) / 365 >= 20 THEN e.sal * 1.1
WHEN d.dname = 'SALES' AND DATEDIFF(NOW(),e.hiredate) / 365 < 20 THEN e.sal * 1.05
WHEN d.dname = 'ACCOUNTING' THEN e.sal + 300
WHEN d.dname = 'RESEARCH' AND e.sal < g.avg THEN e.sal + 200
WHEN e.deptno IS NULL THEN e.sal + 100
ELSE e.sal
END
);
2.3 總結(jié)
- 技能清單
熟練運(yùn)用數(shù)字函數(shù)儿普。
熟練運(yùn)用字符函數(shù)。
熟練運(yùn)用日期函數(shù)掷倔。
熟練運(yùn)用條件函數(shù)眉孩。
3. MySQL的綜合應(yīng)用
3.1 介紹
- 數(shù)據(jù)庫事務(wù)機(jī)制
undo
和redo
日志、開啟事務(wù)勒葱、提交事務(wù)浪汪、回滾事務(wù) - 數(shù)據(jù)的導(dǎo)出和導(dǎo)入
SQL
文件的導(dǎo)入和導(dǎo)出、TXT
文檔的導(dǎo)入與導(dǎo)出 - 綜合案例:設(shè)計(jì)數(shù)據(jù)表
設(shè)計(jì)新聞管理系統(tǒng)的數(shù)據(jù)表凛虽。
3.2 MySQL數(shù)據(jù)庫的事務(wù)機(jī)制
- 事務(wù)概念
SQL
語句直接操作數(shù)據(jù)文件是很危險(xiǎn)的死遭。
MySQL
有5
種日志,其中redo
日志和undo
地址與事務(wù)有關(guān)凯旋。
image.png - 事務(wù)機(jī)制(
Transaction
)
RDBMS
(關(guān)系數(shù)據(jù)庫) =SQL
語句 + 事務(wù)(ACID
)
事務(wù)是一個(gè)或者多個(gè)SQL
語句組成的整體呀潭,要么全部執(zhí)行成功钉迷,要么全部執(zhí)行失敗。 - 管理事務(wù)
默認(rèn)情況下蜗侈,MySQL
執(zhí)行每條SQL
語句都會(huì)自動(dòng)開啟和提交事務(wù)篷牌。
我們可以手動(dòng)管理事務(wù),讓多條SQL
語句納入到一個(gè)事務(wù)之中踏幻。
START TRANSACTION;
SQL語句
[COMMIT | ROLLBACK];
START TRANSACTION;
DELETE FROM t_emp;
DELETE FROM t_dept;
SELECT COUNT(*) FROM t_emp; # 0
SELECT COUNT(*) FROM t_dept; # 0
COMMIT;
-- ROLLBACK;
注意:COMMIT
語句執(zhí)行之前雖然查到的數(shù)據(jù)集合數(shù)目為0
枷颊。但此時(shí)是在redo
文件中查到的結(jié)果,真實(shí)數(shù)據(jù)庫里數(shù)據(jù)還沒有被刪除该面,直到執(zhí)行COMMIT
語句夭苗。
- 事務(wù)的
ACID
屬性
(1) 原子性
一個(gè)事務(wù)中的所有操作要么全部完成,要么全部失敗隔缀。事務(wù)執(zhí)行后题造,不允許停留在中間某個(gè)狀態(tài)。
(2) 一致性
不管在任何給定的時(shí)間猾瘸、并發(fā)事務(wù)有多少界赔,事務(wù)必須保證運(yùn)行結(jié)果的一致性。
(3) 隔離性
隔離性要求事務(wù)不受其他并發(fā)事務(wù)的影響牵触,如同在給定的時(shí)間內(nèi)淮悼,該事務(wù)是數(shù)據(jù)庫唯一運(yùn)行的事務(wù)。
例如:默認(rèn)情況下揽思,A
事務(wù)只能看到日志中該事務(wù)的相關(guān)數(shù)據(jù)袜腥。
(4) 持久性
事務(wù)一旦提交,結(jié)果便是永久性的钉汗。即便發(fā)生宕機(jī)羹令,仍然可以依靠事務(wù)日志完成數(shù)據(jù)的持久化。 - 事務(wù)的四個(gè)隔離級(jí)別
序號(hào) | 隔離級(jí)別 | 功能 |
---|---|---|
1 |
read uncommitted |
讀取未提交數(shù)據(jù) |
2 |
read committed |
讀取已提交數(shù)據(jù) |
3 |
repeatable read |
重復(fù)讀取 |
4 |
serializable |
序列化 |
注釋:默認(rèn)隔離級(jí)別為repeatable read
损痰。
-
買票事務(wù)案例
image.png
-- 查詢面板1
START TRANSACTION;
UPDATE t_emp SET sal = 1;
-- 查詢面板2
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- 設(shè)置當(dāng)前會(huì)話事務(wù)隔離級(jí)別:允許讀取其他事務(wù)未提交數(shù)據(jù)福侈。
START TRANSACTION;
SELECT empno, ename, sal FROM t_emp;
COMMIT;
-- 7369 SMITH 1.00
-- 7499 ALLEN 1.00
-- 7521 WARD 1.00
注釋:①一個(gè)查詢面板就是一個(gè)SESSION
會(huì)話。②isolation
隔離卢未。
-
轉(zhuǎn)賬事務(wù)案例
image.png
-- 查詢面板1
START TRANSACTION;
UPDATE t_emp SET sal = 1;
-- 查詢面板2
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 設(shè)置當(dāng)前會(huì)話事務(wù)隔離級(jí)別:允許讀取其他事務(wù)已提交數(shù)據(jù)
START TRANSACTION;
SELECT empno, ename, sal FROM t_emp;
COMMIT;
-- 7369 SMITH 800.00
-- 7499 ALLEN 1600.00
-- 7521 WARD 1250.00
- 購物案例
image.png
REPEATABLE READ
代表事務(wù)在執(zhí)行中反復(fù)讀取數(shù)據(jù)肪凛,得到的結(jié)果是一致的,不受其他事務(wù)的影響尝丐。
-- 查詢面板1
START TRANSACTION;
UPDATE t_emp SET sal = 1;
COMMIT;
--查詢面板2
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT empno, ename, sal FROM t_emp;
COMMIT;
注意:事務(wù)執(zhí)行SELECT
語句之后显拜,數(shù)據(jù)才會(huì)保存到undo
日志衡奥,之后的查詢結(jié)果才不受其他事務(wù)對(duì)數(shù)據(jù)的修改影響爹袁。
- 事務(wù)的序列化
由于事務(wù)并發(fā)執(zhí)行所帶來的的各種問題,前三種隔離級(jí)別只適用于某些業(yè)務(wù)場(chǎng)景中矮固。序列化隔離失息,讓事務(wù)逐一執(zhí)行譬淳,就不會(huì)產(chǎn)生上述問題了。
該隔離級(jí)別犧牲了事務(wù)的并發(fā)性盹兢,很少使用邻梆。
-- 查詢面板1
START TRANSACTION;
UPDATE t_emp SET sal = 1;
COMMIT;
--查詢面板2
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT empno, ename, sal FROM t_emp;
COMMIT;
3.3 數(shù)據(jù)的持久化
- 數(shù)據(jù)導(dǎo)出與備份的區(qū)別
數(shù)據(jù)導(dǎo)出:導(dǎo)出的只是數(shù)據(jù)文件。
數(shù)據(jù)備份:備份的是數(shù)據(jù)文件绎秒、日志文件浦妄、索引文件等。 - 數(shù)據(jù)導(dǎo)出分類
SQL
文件见芹、文本文件 - 導(dǎo)出
SQL
文件
(1) 命令行語法
mysqldump -uroot -p [no-data] 邏輯庫 > 路徑
? ~ mysqldump -uroot -p demo > /Users/nimengwei/downloads/demo.sql
Enter password:
? ~
(2) 圖形化界面
注釋:當(dāng)數(shù)據(jù)導(dǎo)出為SQL
文件時(shí)剂娄,MySQL
會(huì)生成可以創(chuàng)建這些數(shù)據(jù)的SQL
語句,效率低玄呛。
- 導(dǎo)入
SQL
文件
(1) 命令行語法
USE demo;
SOURCE demo.sql;
? ~ cd /Users/nimengwei/Downloads/sql_file
? sql_file mysql -uroot -p
Enter password:
mysql> USE demo;
Database changed
mysql> SOURCE demo.sql;
Query OK, 0 rows affected (0.00 sec)
mysql>
(2) 圖形化界面
- 圖形化界面導(dǎo)出為文本文件
(1) 導(dǎo)出數(shù)據(jù)結(jié)構(gòu)
(2) 導(dǎo)出向?qū)?數(shù)據(jù))
注釋:當(dāng)數(shù)據(jù)導(dǎo)出為文本文件時(shí)阅懦,由于文本文件中沒有SQL
語句,MySQL
導(dǎo)出時(shí)不執(zhí)行詞法分析和語法優(yōu)化徘铝,效率高耳胎。
- 圖形化界面導(dǎo)入文本文件
(1) 導(dǎo)入數(shù)據(jù)結(jié)構(gòu)
(2) 導(dǎo)入向?qū)?數(shù)據(jù))
3.4 綜合案例:新聞管理系統(tǒng)數(shù)據(jù)庫設(shè)計(jì)
-
新聞管理系統(tǒng)成員
image.png -
新聞?dòng)心男傩?/p>
image.png - 數(shù)據(jù)庫
ER
圖設(shè)計(jì)
image.png - 數(shù)據(jù)加密
(1) 數(shù)據(jù)加密
分類:對(duì)稱加密、非對(duì)稱加密
(2) 對(duì)稱加密
加密和解密使用同一個(gè)秘鑰惕它。
分類:DES
加密(已淘汰)怕午、AES
加密
(3) 非對(duì)稱加密
加密和解密使用不同的秘鑰。
公鑰可以解密私鑰加密的數(shù)據(jù)怠缸,私鑰可以解密公鑰加密的數(shù)據(jù)诗轻。
分類:RSA
加密、DSA
加密揭北、ECC
加密 -
AES
加密函數(shù)
MySQL
提供了AES
加密和解密的函數(shù)扳炬。
AES_ENCRYPT(原始數(shù)據(jù), 秘鑰字符串);
AES
解密要使用與加密相同的秘鑰,才能解密出原始數(shù)據(jù)搔体。
AES_DECRYPT(加密結(jié)果, 秘鑰字符串);
SELECT AES_ENCRYPT('你好世界','ABC123456');
# èZ?KaB§7^SàT\-H? 亂碼了恨樟,可轉(zhuǎn)化為16進(jìn)制解決亂碼
SELECT HEX(AES_ENCRYPT('你好世界','ABC123456'));
# hex為2二進(jìn)制轉(zhuǎn)16進(jìn)制
# E85A104B6142A7375E53C0545CAD48EE
SELECT AES_DECRYPT(UNHEX('E85A104B6142A7375E53C0545CAD48EE'), 'ABC123456')
# unhex為16進(jìn)制轉(zhuǎn)2進(jìn)制
# 你好世界
- 數(shù)據(jù)庫實(shí)現(xiàn)
(1) 創(chuàng)建數(shù)據(jù)庫
# 創(chuàng)建vega數(shù)據(jù)庫
CREATE DATABASE vega;
# 切換數(shù)據(jù)庫
USE vega;
(2) t_type
文章類型表
數(shù)據(jù)表中數(shù)據(jù)量不大時(shí),可以不添加索引疚俱。例如:t_type
文章類型表劝术,t_role
角色類型表。
# 創(chuàng)建文章類型表
CREATE TABLE t_type(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
type VARCHAR(20) NOT NULL UNIQUE
);
# 文章類型表插入數(shù)據(jù)
INSERT INTO t_type(type)
VALUES("要聞"), ("體育"), ("科技"), ("娛樂"), ("歷史");
(3) t_role
角色類型表
# 創(chuàng)建角色類型表
CREATE TABLE t_role(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
role VARCHAR(20) NOT NULL UNIQUE
);
# 角色類型表插入數(shù)據(jù)
INSERT INTO t_role(role)
VALUES("管理員"), ("新聞編輯");
(4) t_user
用戶表
數(shù)據(jù)表中數(shù)據(jù)量很大呆奕,并且經(jīng)常使用某些字段查找數(shù)據(jù)养晋,則應(yīng)該對(duì)這些字段創(chuàng)建索引。例如:t_user
表中的username
梁钾。
# 創(chuàng)建用戶表
CREATE TABLE t_user(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) NOT NULL UNIQUE,
password VARCHAR(500) NOT NULL,
email VARCHAR(100) NOT NULL,
role_id INT UNSIGNED NOT NULL,
INDEX(username)
);
# 用戶表插入數(shù)據(jù)
INSERT IGNORE INTO t_user(username, password, email, role_id) VALUES
('admin', HEX(AES_ENCRYPT('123456','HelloWord')), 'admin@163.com', 1),
('scott', HEX(AES_ENCRYPT('123456','HelloWord')), 'scott@163.com', 2);
(5) t_news
新聞表
新聞內(nèi)容數(shù)據(jù)的特點(diǎn)為:數(shù)據(jù)量大绳泉、安全級(jí)別低,適合存儲(chǔ)在mongodb
數(shù)據(jù)庫中姆泻。通過content_id
查找零酪。
# 創(chuàng)建新聞表
CREATE TABLE t_news(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(40) NOT NULL,
editor_id INT UNSIGNED NOT NULL,
type_id INT UNSIGNED NOT NULL,
content_id VARCHAR(24) NOT NULL,
is_top TINYINT UNSIGNED NOT NULL,
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
state ENUM('草稿', '待審批', '已審批', '隱藏') NOT NULL,
INDEX(editor_id),
INDEX(type_id),
INDEX(state),
INDEX(is_top),
INDEX(create_time)
);
3.5 總結(jié)
- 技能清單
學(xué)習(xí)了事務(wù)機(jī)制的原理和特性冒嫡。
掌握了事務(wù)的管理。
掌握了數(shù)據(jù)導(dǎo)出與導(dǎo)入的操作四苇。
完成了新聞管理系統(tǒng)數(shù)據(jù)表的設(shè)計(jì)孝凌。
4. MySQL與Python交互
4.1 介紹
-
MySQL Connector
模塊
數(shù)據(jù)庫連接池、預(yù)編譯SQL
月腋、CRUD
操作蟀架、事務(wù)管理、異常處理 - 新聞管理系統(tǒng)
新聞管理榆骚、用戶管理辜窑、系統(tǒng)登錄、數(shù)據(jù)分頁等
4.2 MySQL與Python的交互
-
MySQL Connector
模塊
MySQL Connector
是MySQL
官方的驅(qū)動(dòng)模塊寨躁,兼容性特別好穆碎。
? ~ pip3 install mysql-connector
...
Successfully installed mysql-connector-2.2.9
- 創(chuàng)建連接
(1) 語法一
import mysql.connector
con = mysql.connector.connect(
host="localhost",
port=3306,
user="root",
password="299***",
database="demo"
)
con.close()
(2) 語法二
import mysql.connector
config = {
"host":"localhost",
"port": 3306,
"user": "root",
"password": "299***",
"database": "demo"
}
con = mysql.connector.connect(**config)
con.close()
- 游標(biāo)(
Cursor
)
MySQL Connector
里的游標(biāo)用來執(zhí)行SQL
語句,查詢的結(jié)果集也會(huì)保存在游標(biāo)中职恳。
cursor = con.cursor()
cursor.execute(sql語句)
import mysql.connector
con = mysql.connector.connect(
host="localhost",
port=3306,
user="root",
password="299***",
database="demo"
)
cursor = con.cursor()
sql = "SELECT empno, ename, hiredate FROM t_emp;"
cursor.execute(sql)
for item in cursor:
print(item[0], item[1], item[2])
# 7369 SMITH 1980-12-17
# 7499 ALLEN 1981-02-20
# ...
con.close()
-
SQL
注入攻擊
import mysql.connector
config = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "299***",
"database": "vega"
}
# 連接數(shù)據(jù)庫
con = mysql.connector.connect(**config)
# 獲取游標(biāo)
cursor = con.cursor()
username = "1 OR 1=1"
password = "1 OR 1=1"
sql = "SELECT COUNT(*) FROM t_user WHERE username=%s" \
" AND AES_DECRYPT(UNHEX(password), 'HelloWord')=%s;"
cursor.execute(sql%(username, password))
print(cursor.fetchone()[0]) # 2
# 關(guān)閉數(shù)據(jù)庫連接
con.close()
注意:密碼必須是字符串格式所禀。
-
SQL
注入攻擊的危害
由于SQL
語句是解釋型語言,所以在拼接SQL
語句的時(shí)候放钦,容易被注入惡意的SQL
語句色徘。
id = "1 OR 1=1"
sql = "DELETE FROM t_news WHERE id={}".format(id)
-
SQL
預(yù)編譯機(jī)制
(1)SQL
預(yù)編譯機(jī)制
預(yù)編譯SQL
就是數(shù)據(jù)庫提前把SQL
語句編譯成二進(jìn)制,這樣反復(fù)執(zhí)行同一條SQL
語句的效率就會(huì)提升操禀。
(2) 抵御注入攻擊
SQL
語句編譯的過程中褂策,關(guān)鍵字已經(jīng)被解析過了,所以向編譯后的SQL
語句傳入?yún)?shù)颓屑,參數(shù)都被當(dāng)做字符串處理斤寂,數(shù)據(jù)庫不會(huì)解析其中注入的SQL
語句。
注釋:預(yù)編譯機(jī)制既可以提升SQL
語句的執(zhí)行效率揪惦,又可以抵御注入攻擊遍搞。 - 抵御注入攻擊
import mysql.connector
config = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "299***",
"database": "vega"
}
# 連接數(shù)據(jù)庫
con = mysql.connector.connect(**config)
# 獲取游標(biāo)
cursor = con.cursor()
username = "1 OR 1=1"
password = "1 OR 1=1"
sql = "SELECT COUNT(*) FROM t_user WHERE username=%s" \
" AND AES_DECRYPT(UNHEX(password), 'HelloWord')=%s;"
cursor.execute(sql, (username, password))
print(cursor.fetchone()[0]) # 0
# 關(guān)閉數(shù)據(jù)庫連接
con.close()
注意:execute
的第二個(gè)參數(shù)為元組或數(shù)組,例如: [a]
器腋、(a,)
溪猿。
- 事務(wù)控制
con.start_transaction([事務(wù)隔離機(jī)制])
con.commit()
con.rollback()
- 異常處理
(1) 語法
try:
con = mysql.connector.connect(...)
[ con.start_transaction() ]
...
con.commit()
except Exception as e:
[ con.rollback() ]
print(e)
finally:
if "con" in dir():
con.close()
(2) 示例
import mysql.connector
try:
con = mysql.connector.connect(
host='localhost',
port=3306,
user='root',
password='299***',
database='demo'
)
con.start_transaction()
cursor = con.cursor()
sql = "INSERT INTO t_emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) " \
"VALUES(%s, %s, %s, %s, %s, %s, %s, %s);"
cursor.execute(sql, (9600, '趙娜', 'SALESMAN', None,'1998-09-08', 2000, None, 10))
con.commit()
except Exception as e:
if 'con' in dir():
con.rollback()
print(e)
finally:
if 'con' in dir():
con.close()
- 數(shù)據(jù)庫連接池技術(shù)
數(shù)據(jù)庫連接是一種關(guān)鍵的、有限的纫塌、昂貴的資源诊县,在并發(fā)執(zhí)行的應(yīng)用程序中體現(xiàn)的尤為突出。TCP
連接需要三次握手措左,四次揮手依痊,然后數(shù)據(jù)庫還要驗(yàn)證用戶信息。
數(shù)據(jù)庫連接池(ConnectionPool
)預(yù)先創(chuàng)建出一些數(shù)據(jù)庫連接媳荒,然后緩存起來抗悍,避免了程序語言反復(fù)創(chuàng)建和銷毀連接的昂貴代價(jià)。
import mysql.connector.pooling
config = {
'host': 'localhost',
'port': '3306',
'user': 'root',
'password': '299***',
'database': 'demo'
}
try:
pool = mysql.connector.pooling.MySQLConnectionPool(
**config,
pool_size=10
)
con = pool.get_connection()
con.start_transaction()
cursor = con.cursor()
sql = "UPDATE t_emp SET sal=sal+%s WHERE deptno=%s;"
cursor.execute(sql, (200, 20))
con.commit()
except Exception as e:
if "con" in dir():
con.rollback()
print(e)
finally:
if "con" in dir():
con.close()
注意:使用數(shù)據(jù)庫連接池(ConnectionPool
)也需要關(guān)閉(close
)钳枕。
- 刪除數(shù)據(jù)
(1) DELETE
語句刪除記錄
import mysql.connector.pooling
config = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': '299***',
'database': 'demo'
}
try:
pool = mysql.connector.pooling.MySQLConnectionPool(
**config,
pool_size=10
)
con = pool.get_connection()
con.start_transaction()
cursor = con.cursor()
sql = "DELETE e, d FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno " \
"WHERE d.deptno=20;"
cursor.execute(sql)
con.commit()
except Exception as e:
if 'con' in dir():
con.rollback()
print(e)
finally:
if "con" in dir():
con.close()
(2) TRUNCATE
語句快速刪除記錄
TRUNCATE
語句是在事務(wù)機(jī)制之外刪除記錄缴渊。
import mysql.connector.pooling
config = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': '299***',
'database': 'demo'
}
try:
pool = mysql.connector.pooling.MySQLConnectionPool(
**config,
pool_size=10
)
con = pool.get_connection()
cursor = con.cursor()
sql = "TRUNCATE TABLE t_emp"
cursor.execute(sql)
except Exception as e:
print(e)
- 循環(huán)執(zhí)行
SQL
語句
(1) for
循環(huán)執(zhí)行execute()
函數(shù)
import mysql.connector.pooling
config = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': '299***',
'database': 'demo'
}
try:
pool = mysql.connector.pooling.MySQLConnectionPool(
**config,
pool_size=10
)
con = pool.get_connection()
con.start_transaction()
cursor = con.cursor()
sql = "INSERT INTO t_dept(deptno, dname, loc) VALUES (%s, %s, %s);"
data = [[50, '部門1', '北京'], [60, '部門2', '上海']]
for item in data:
cursor.execute(sql, item)
con.commit()
except Exception as e:
if 'con' in dir():
con.rollback()
print(e)
finally:
if "con" in dir():
con.close()
(2) 游標(biāo)(cursor
)對(duì)象中的executemany()
函數(shù)可以反復(fù)執(zhí)行一條SQL
語句。
import mysql.connector.pooling
config = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': '299***',
'database': 'demo'
}
try:
pool = mysql.connector.pooling.MySQLConnectionPool(
**config,
pool_size=10
)
con = pool.get_connection()
con.start_transaction()
cursor = con.cursor()
sql = "INSERT INTO t_dept(deptno, dname, loc) VALUES (%s, %s, %s);"
data = [[70, '部門1', '北京'], [80, '部門2', '上海']]
cursor.executemany(sql, data)
con.commit()
except Exception as e:
if 'con' in dir():
con.rollback()
print(e)
finally:
if "con" in dir():
con.close()
- 使用
INSERT
語句鱼炒,把部門平均底薪超過公司平均底薪這樣的部門里的員工信息導(dǎo)入到t_emp_new
表里衔沼,并且讓這些員工隸屬于sales
部門。
編程語言中昔瞧,數(shù)據(jù)庫查詢結(jié)果可以通過變量保存指蚁,比直接通過SQL
語句操作數(shù)據(jù)庫的寫法簡(jiǎn)單。
import mysql.connector.pooling
config = {
'host': 'localhost',
'port': '3306',
'user': 'root',
'password': '299***',
'database': 'demo'
}
try:
pool = mysql.connector.pooling.MySQLConnectionPool(
**config,
pool_size=10
)
con = pool.get_connection()
con.start_transaction()
cursor = con.cursor()
# 創(chuàng)建數(shù)據(jù)表
sql = "CREATE TABLE t_emp_new LIKE t_emp;"
cursor.execute(sql)
# 公司平均底薪
sql = "SELECT AVG(sal) as avg FROM t_emp;"
cursor.execute(sql)
avg = cursor.fetchone()[0]
# print(avg) # 2073.214286
# 部門底薪超過公司平均底薪的部門
sql = "SELECT deptno FROM t_emp GROUP BY deptno HAVING AVG(sal) >= %s;"
cursor.execute(sql, (avg,))
deptnos = cursor.fetchall()
# print(deptnos) # [(10,), (20,)]
# 符合條件的部門員工導(dǎo)入到新表
deptnos_str = '('
for index in range(len(deptnos)):
if index == len(deptnos) - 1:
deptnos_str += (str(deptnos[index][0]))
else:
deptnos_str += (str(deptnos[index][0]) + ',')
deptnos_str += ')'
sql = "INSERT INTO t_emp_new (SELECT * FROM t_emp WHERE deptno IN {});".format(deptnos_str)
cursor.execute(sql)
sql = "DELETE FROM t_emp WHERE deptno IN {};".format(deptnos_str)
cursor.execute(sql)
# 將t_emp_new表的員工部門修改為sales部門
sql = "SELECT deptno FROM t_dept WHERE dname=%s;"
cursor.execute(sql, ['SALES'])
new_emptno = cursor.fetchone()[0]
print(new_emptno)
sql = "UPDATE t_emp_new SET deptno=%s"
cursor.execute(sql, [new_emptno])
con.commit()
except Exception as e:
if 'con' in dir():
con.rollback()
print(e)
finally:
if "con" in dir():
con.close()
注意:① 'CREATE TABLE t_emp_new LIKE t_emp;'
表示使用t_emp
表的結(jié)構(gòu)創(chuàng)建t_emp_new
表自晰。② CREATE TABLE
語句為DDL
語句凝化,不受事務(wù)控制。③ 由于不知道符合條件的部門個(gè)數(shù)酬荞,因此該案例只能使用字符串拼接搓劫,不能使用字符串格式化。 ④ INSERT INTO t_emp_new 查詢出的表結(jié)果;
語法可以將查詢出的數(shù)據(jù)表集合插入到t_emp_new
表中枪向。
- 編寫一個(gè)
INSERT
語句秘蛔,向部門表插入兩條記錄,每條記錄都在部門原有最大主鍵值的基礎(chǔ)上加10
辨液。
(1) 不支持邊插入,邊查詢本表數(shù)據(jù)
例如:INSERT INTO 表名(字段1,字段2, ...) VALUES(值1,值2,...);
INSERT INTO t_dept(deptno, dname, loc)
VALUES((SELECT MAX(deotno) FROM t_dept) + 10, "A部門", "南京");
# 報(bào)錯(cuò) Unknown column 'deotno' in 'field list', Time: 0.014000s
(2) 可以先查詢出數(shù)據(jù)表燎悍,再寫入
例如:INSERT INTO 表名 數(shù)據(jù)集;
INSERT INTO t_dept (SELECT MAX(deptno) + 10, "A部門", "南京" FROM t_dept);
INSERT INTO t_dept (SELECT MAX(deptno) + 10, "A部門", "南京" FROM t_dept) UNION
(SELECT MAX(deptno) + 20, "B部門", "上海" FROM t_dept);
(3) Python
語言實(shí)現(xiàn)
import mysql.connector.pooling
config = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': '299***',
'database': 'demo'
}
try:
pool = mysql.connector.pooling.MySQLConnectionPool(
**config,
pool_size=10
)
con = pool.get_connection()
con.start_transaction()
cursor = con.cursor()
sql = "INSERT INTO t_dept " \
"(SELECT MAX(deptno) + 10, %s, %s FROM t_dept) " \
"UNION " \
"(SELECT MAX(deptno) + 20, %s, %s FROM t_dept);"
cursor.execute(sql, ('A部門', '北京', 'B部門', '上海'))
con.commit()
except Exception as e:
if 'con' in dir():
con.rollback()
print(e)
finally:
if "con" in dir():
con.close()
4.3 總結(jié)
- 技能清單
掌握了數(shù)據(jù)庫連接池技術(shù)
掌握了Python
程序的CRUD
操作
掌握了用預(yù)編譯SQL
抵御SQL
注入攻擊
5. 開發(fā)新聞管理系統(tǒng)
- 第三方模塊
(1) 升級(jí)pip
? ~ python3 -m pip install --upgrade pip
(2) 安裝colorama
? ~ pip3 install colorama
向控制臺(tái)輸出彩色文字
from colorama import Back, Fore, Style
print(Fore.LIGHTBLUE_EX, 'HelloWord') # 設(shè)置字體顏色
print('HelloWord')
print(Back.LIGHTRED_EX, 'HelloWord') # 設(shè)置背景色
print('HelloWord')
print(Style.RESET_ALL, 'HelloWord') # 重置樣式
- 項(xiàng)目介紹
(1) 新建項(xiàng)目
(2) 項(xiàng)目結(jié)構(gòu)
vega
- db
奏路、service
斜脂、app.py
(3) 管理員身份操作流程圖
- 代碼地址
https://github.com/nmwei/database-vega - 代碼示例(部分)
(1)mysql_db
提供數(shù)據(jù)庫連接池
import mysql.connector.pooling
__config = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': '299792',
'database': 'vega'
}
try:
pool = mysql.connector.pooling.MySQLConnectionPool(
**__config,
pool_size=10
)
except Exception as e:
print(e)
(2) dao
文件用來操作數(shù)據(jù)庫,以user_dao.py
為例片任。
from db.mysql_db import pool
class UserDao:
# 驗(yàn)證用戶登錄
def login(self, username, password):
try:
con = pool.get_connection()
cursor = con.cursor()
sql = "SELECT COUNT(*) FROM t_user WHERE username=%s AND " \
"AES_DECRYPT(UNHEX(password), 'HelloWord')=%s;"
cursor.execute(sql, (username, password))
count = cursor.fetchone()[0]
# Python中的三元運(yùn)算符
return True if count == 1 else False
except Exception as e:
print(e)
finally:
if "con" in dir():
con.close()
...
(3) service
文件用來調(diào)用dao
函數(shù)氛濒,并處理業(yè)務(wù)邏輯涝动。以user_service.py
為例醋粟。
from db.user_dao import UserDao
class UserService:
__user_dao = UserDao()
# 驗(yàn)證用戶登錄
def login(self, username, password):
return self.__user_dao.login(username, password)
...
(4) app.py
程序入口
from colorama import Fore, Style
from getpass import getpass
from service.user_service import UserService
from service.news_service import NewsService
from service.role_service import RoleService
import os
import sys
import time
__user_service = UserService()
__news_service = NewsService()
__role_service = RoleService()
while True: # 輪詢操作
os.system('clear') # 如果是window系統(tǒng)鼻吮,使用cls
print(Fore.LIGHTBLUE_EX, '\n\t=================')
print(Fore.LIGHTBLUE_EX, '\n\t歡迎使用新聞管理系統(tǒng)')
print(Fore.LIGHTBLUE_EX, '\n\t=================')
print(Fore.LIGHTGREEN_EX, '\n\t1. 登錄系統(tǒng)')
print(Fore.LIGHTGREEN_EX, '\n\t2. 退出系統(tǒng)')
print(Style.RESET_ALL) # 重置樣式
opt = input("\n\t請(qǐng)輸入操作編號(hào): ")
if opt == '1':
username = input('\n\t用戶名: ')
password = getpass('\n\t密碼: ') # 使輸密碼過程不可見
result = __user_service.login(username, password)
# 登錄成功
...
注意:①Python
中的三元運(yùn)算符:True if count == 1 else False
违柏。②數(shù)據(jù)庫中管理員用戶名密碼為:admin
123456
畜伐。
- 文/潘曉璐 我一進(jìn)店門世舰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人姊氓,你說我怎么就攤上這事读跷。” “怎么了荡短?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長弯院。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么贴妻? 我笑而不...
- 正文 為了忘掉前任蝙斜,我火速辦了婚禮名惩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘孕荠。我一直安慰自己娩鹉,他們只是感情好,可當(dāng)我...
- 文/花漫 我一把揭開白布稚伍。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瑟捣。 梳的紋絲不亂的頭發(fā)上芙扎,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
- 序言:老撾萬榮一對(duì)情侶失蹤羔砾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愤诱,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡鲜棠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瓮恭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雄坪。...
- 正文 年R本政府宣布阔挠,位于F島的核電站,受9級(jí)特大地震影響脑蠕,放射性物質(zhì)發(fā)生泄漏购撼。R本人自食惡果不足惜,卻給世界環(huán)境...
- 文/蒙蒙 一谴仙、第九天 我趴在偏房一處隱蔽的房頂上張望迂求。 院中可真熱鬧,春花似錦晃跺、人聲如沸揩局。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽谐腰。三九已至孕豹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間十气,已是汗流浹背励背。 一陣腳步聲響...
- 正文 我出身青樓,卻偏偏與公主長得像芹枷,于是被迫代替她去往敵國和親衅疙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- MySQL數(shù)據(jù)庫對(duì)象與應(yīng)用 2.1-MySQL數(shù)據(jù)類型 庫建立好之后基本不動(dòng),和我們接觸最頻繁的是表. 建表就是聲...
- 一、 left join翁逞, right join肋杖, inner join區(qū)別? left join(左聯(lián)接) 返回...
- MySQL性能優(yōu)化的21個(gè)最佳實(shí)踐 TechTarget中國原創(chuàng)內(nèi)容挖函,原文鏈接:http://www.search...
- 【變量名與對(duì)象】 在Python中状植,變量名稱就像貼在對(duì)象上的標(biāo)簽一樣。每個(gè)標(biāo)簽上都有一個(gè)唯一的名稱怨喘,并且每次只能用...