数据库编程
数据库
概念

分类







Oracle

Mysql

去IOE

NoSQL

数据库流行度排名

MYSQL

安装

SQL语句

DCL

DDL
删除用户

创建数据库

删除数据库
![]()
创建表

DESC

练习


PRIMARY KEY主键

索引Index

约束Constraint

PRIMARY KEY约束
![]()
外键约束Foreign key

视图

数据类型
MYSQL中的数据类型


关系操作

DML---CRUD增删改查
Insert语句


Update语句

Delete语句

Select语句

查询
![]()

Limit子句

Where子句


Order by子句
![]()

DISTINCT不返回重复记录

聚合函数


分组查询


子查询

连接Join

内连接

外连接


自连接

事务Transaction

原子性:要求事务中的所有操作不可分割,不能做了一部分操作,还剩下一部分;
一致性:多个事务并行执行的结果,应该和事务排队执行的结果一致。如果事务的并行执行和多线程读写共享资源一样不可预期,就不能保证一致性;
隔离性,就是指多个事务访问共同的数据了,应该互不干扰。隔离性指的是究竟在一个事物处理期间,其他事务能不能访问的问题;
持久性:比较好理解,就是事务提交后,数据不能丢失。
MYSQL隔离级别






事务语法

数据仓库和数据库的区别

其他概念
游标Cursor

存储过程、触发器

数据库开发
驱动

pymysql使用
$pip install pymysql
创建数据库和表
CREATE DATABASE IF NOT EXISTS school; SHOW DATABASES; USE school;
CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
连接Connect


![]()
import pymysql conn = None try: #建立连接 conn = pymysql.connect('192.168.10.166','wayne','wayne','test') print(conn.ping(False)) finally: if conn: conn.close()
游标Cursor

操作数据库
![]()
新增记录
![]()
import pymysql conn = None try: #建立连接 conn = pymysql.connect('192.168.10.166','wayne','wayne','school') print(conn.ping(False)) #获取游标 cursor = conn.cursor() insert_sql = "insert into student (id,name,age) values(10,'tom',20)" rows = cursor.execute(insert_sql) print(rows) cursor.close() finally: if conn: conn.close()

事务管理

import pymysql conn = None cursor = None try: conn = pymysql.connect('192.168.10.166','wayne','wayne','school') cursor = conn.cursor() insert_sql = "insert into student (name,age) values('tom',21)" rows = cursor.execute(insert_sql) print(rows) conn.commit() except: conn.rollback() finally: if cursor: cursor.close() if conn: conn.close()
批量增加数据
import pymysql conn = None cursor = None try: conn = pymysql.connect('192.168.10.166','wayne','wayne','school') cursor = conn.cursor() for i in range(5): insert_sql = "insert into student (name,age) values('tom',21)" rows = cursor.execute(insert_sql) conn.commit() except: conn.rollback() finally: if cursor: cursor.close() if conn: conn.close()
一般流程

查询

import pymysql conn = None cursor = None try: conn = pymysql.connect('192.168.10.166','wayne','wayne','school') cursor = conn.cursor() sql = "select * from student" rows = cursor.execute(sql) #返回影响行数 print(cursor.fetchone()) print(cursor.fetchmany(2)) print(cursor.fetchall()) except: pass finally: if cursor: cursor.close() if conn: conn.close()

带列名查询

import pymysql from pymysql.cursors import DictCursor conn = pymysql.connect('192.168.10.166','wayne','wayne','school') cursor = conn.cursor(DictCursor) sql = "select * from student" rows = cursor.execute(sql) print(cursor.fetchone())#{'id': 1, 'name': 'tom', 'age': 20} print(cursor.fetchall())#[{'id': 2, 'name': 'tom', 'age': 21}]

SQL注入攻击

#找出用户id为5的用户信息语句如下: import pymysql conn = pymysql.connect('192.168.10.166','wayne','wayne','school') cursor = conn.cursor() userid = '5' sql = 'select * from student where id = {}'.format(userid) cursor.execute(sql) print(cursor.fetchall()) #((5, 'zqk', 23),)
#userid可以变,例如从客户端request请求中获取,直接拼接到查询字符串中 #当userid='5 or 1=1'呢? import pymysql conn = pymysql.connect('192.168.10.166','wayne','wayne','school') cursor = conn.cursor() userid = '5 or 1=1' sql = 'select * from student where id = {}'.format(userid) cursor.execute(sql) print(cursor.fetchall()) #((1, 'tom', 20), (2, 'tom', 21), (3, 'cy', 22), (4, 'xu', 24), (5, 'zqk', 23)) #运行结果返回了数据库全部数据

import pymysql conn = pymysql.connect('192.168.10.166','wayne','wayne','school') cursor = conn.cursor() userid = '5 or 1=1' sql1 = 'SELECT * FROM student WHERE id = %s' cursor.execute(sql1,(userid,)) #参数化查询 print(cursor.fetchall()) print('~~~~~~~~~~~~~~') sql2 = "SELECT * FROM student WHERE name like %(name)s and %(age)s" #参数化查询 cursor.execute(sql2,{'name':'tom','age':19}) print(cursor.fetchall()) if cursor: cursor.close() if conn: conn.close() #运行结果如下: D:\Anaconda3\lib\site-packages\pymysql\cursors.py:166: Warning: (1292, "Truncated incorrect DOUBLE value: '5 or 1=1'") result = self._query(query) ((5, 'zqk', 23),) ~~~~~~~~~~~~~~ ((1, 'tom', 20), (2, 'tom', 21))
参数化查询为什么提高效率?

上下文支持
查看连接类和游标类的源码
#连接类 class Connection(object): def __enter__(self): """Context manager that returns a Cursor""" return self.cursor() def __exit__(self, exc, value, traceback): """On successful exit, commit. On exception, rollback""" if exc: self.rollback() else: self.commit()
#游标类 class Cursor(object): def __enter__(self): """Context manager that returns a Cursor""" return self.cursor() def __exit__(self, exc, value, traceback): """On successful exit, commit. On exception, rollback""" if exc: self.rollback() else: self.commit()

#使用游标的上下文 import pymysql conn = pymysql.connect('192.168.10.166','wayne','wayne','school') try: with conn.cursor() as cursor: for i in range(3): insert_sql = "insert into student (name,age) values('tom{0}',21+{0})".format(i) rows = cursor.execute(insert_sql) conn.commit() #此时使用这个关闭的cursor,会抛异常 # sql = "select * from student" # cursor.execute(sql) # print(cursor.fetchall()) except Exception as e: print(e) conn.rollback() finally: conn.close()
#使用连接的上下文 import pymysql conn = pymysql.connect('192.168.10.166','wayne','wayne','school') with conn as cursor: for i in range(3): insert_sql = "insert into student (name,age) values('tom{0}',21+{0})".format(i) rows = cursor.execute(insert_sql) sql = "select * from student" cursor.execute(sql) print(cursor.fetchall()) #关闭 cursor.close() conn.close()

#同时使用连接类和游标类的上下文管理 import pymysql conn = pymysql.connect('192.168.10.166','wayne','wayne','school') with conn as cursor: with cursor: sql = "select * from student" cursor.execute(sql) print(cursor.fetchall()) #关闭 conn.close()
![]()
连接池的实现



from queue import Queue import pymysql class ConnPool: def __init__(self,size,*args,**kwargs): if not isinstance(size,int)or size<1: size = 8 self._pool = Queue(size) for i in range(size): self._pool.put(pymysql.connect(*args,**kwargs)) def get_conn(self): return self._pool.get() #阻塞 def return_conn(self,conn): self._pool.put(conn) #使用连接池 pool = ConnPool(4,'192.168.10.166','wayne','wayne','school') #获取一个连接 conn = pool.get_conn() with conn as cursor: with cursor: sql = "SELECT * FROM student" cursor.execute(sql) print(cursor.fetchone()) sql = "SHOW PROCESSLIST" #观察连接,权限小只能看自己的 cursor.execute(sql) for x in cursor: print(x) #归还连接 pool.return_conn(conn)
![]()
class ConnPool: def __enter__(self): return self.get_conn() def __exit__(self, exc_type, exc_val, exc_tb): #归还谁呢? pass

from queue import Queue import pymysql import threading class ConnPool: def __init__(self,size,*args,**kwargs): if not isinstance(size,int)or size<1: size = 8 self._pool = Queue(size) for i in range(size): self._pool.put(pymysql.connect(*args,**kwargs)) self.local = threading.local() def get_conn(self): return self._pool.get() #阻塞 def return_conn(self,conn): self._pool.put(conn) def __enter__(self): #self.local.conn在当前线程不存在抛属性异常 if getattr(self.local,'conn',None) is None: self.local.conn = self.get_conn() return self.local.conn.cursor() #返回一个游标 def __exit__(self, exc_type, exc_val, exc_tb): if exc_type: self.local.conn.rollback() else: self.local.conm.commit() self.return_conn(self.local.conn) self.local.conn = None #使用连接池 pool = ConnPool(4,'192.168.10.166','wayne','wayne','school') #获取一个连接 conn = pool.get_conn() with conn as cursor: #自动拿连接并归还,还自动提交和回滚 with cursor: sql = "SELECT * FROM student" cursor.execute(sql) print(cursor.fetchone()) sql = "SHOW PROCESSLIST" #观察连接,权限小只能看自己的 cursor.execute(sql) for x in cursor: #对结果记录进行迭代 print(x)

with conn as cursor:
with cursor:
threading.Thread(target=xxx,args=(cursor,))

做一枚奔跑的老少年!

浙公网安备 33010602011771号