任务:python
12.5 游标
12.6 mysql链接池
12.7 设计表结构mysql
笔记:sql
咱们先来看一个例子:数据库
接下来,咱们经过python代码增长一条数据到数据库中,代码以下:编程
import MySQLdb安全
def connect_mysql():app
db_config = {dom
'host': '192.168.48.128',函数
'port': 3306,性能
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
cus = cnx.cursor()
sql = ''' create table test(id int not null);insert into test(id) values (100);'''
try:
cus.execute(sql)
cus.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('Error')
# raise e
finally:
cnx.close()
结果:
Error
查看数据库中的数据:select * from employees;并无发生变化
解释:
在咱们插入数据雇佣时间字段:hire_date的时候,故意把时间写错,致使异常发生,捕获到异常以后,打印Error,最后关闭mysql链接。cus = cnx.cursor()是建立一个游标对象,具体咱们在后面进行介绍。
1,建立游标对象
Import MySQLdb
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
cus = cnx.cursor()
这样就是建立一个游标对象,之后咱们对mysql的各类操做都是基于游标进行操做,后面咱们将详细介绍。
在了解该方法以前,咱们先来了解什么叫作游标,
游标(cursor)
游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果
用户能够用SQL语句逐一从游标中获取记录,并赋给主变量,交由python进一步处理,一组主变量一次只能存放一条记录
仅使用主变量并不能彻底知足SQL语句向应用程序输出数据的要求
1.游标和游标的优势
在数据库中,游标是一个十分重要的概念。游标提供了一种对从表中检索出的数据进行操做的灵活手段,就本质而言,游标其实是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标老是与一条SQL 选择语句相关联由于游标由结果集(能够是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向特定记录的游标位置组成。当决定对结果集进行处理时,必须声明一个指向该结果集的游标。
经常使用方法:
cursor():建立游标对象
close():关闭此游标对象
fetchone():获得结果集的下一行
fetchmany([size = cursor.arraysize]):获得结果集的下几行
fetchall():获得结果集中剩下的全部行
excute(sql[, args]):执行一个数据库查询或命令
executemany (sql, args):执行多个数据库查询或命令
下面咱们来看一个例子:
import MySQLdb
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
cus = cnx.cursor()
sql = '''select * from employees;'''
try:
cus.execute(sql)
result1 = cus.fetchone()
print('result1:')
print(result1)
result2 = cus.fetchmany(1)
print('result2:')
print(result2)
result3 = cus.fetchall()
print('result3:')
print(result3) cus.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
结果:
result1:
(1001L, u'lingjiang', u'M', datetime.date(2015, 4, 1))
result2:
((1002L, u'xiang', u'M', datetime.date(2015, 4, 1)),)
result3:
((1003L, u'shang', u'M', datetime.date(2015, 4, 1)),)
解释:
1,先经过MySQLdb.connect(**db_config)创建mysql链接对象
2,在经过 = cnx.cursor()建立游标
3,fetchone():在最终搜索的数据中去一条数据
4,fetchmany(1)在接下来的数据中在去1行的数据,这个数字能够自定义,定义多少就是在结果集中取多少条数据。
5,fetchall()是在全部的结果中搞出来全部的数据。
对于excute()和excutemany()的方法,咱们会在以一节详细分析他们的区别。
执行多条语句的sql时要注意:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/9/18 22:17
# @Author : lingxiangxiang
# @File : domon3.py
from demon2 import connect_mysql
import MySQLdb
def connect_mysql():
db_config = {
"host": "192.168.48.128",
"port": 3306,
"user": "xiang",
"passwd": "123456",
"db": "python",
"charset": "utf8"
}
try:
cnx = MySQLdb.connect(**db_config)
except Exception as e:
raise e
return cnx
if __name__ == "__main__":
sql = "select * from tmp;"
sql1 = "insert into tmp(id) value (%s);"
param = []
for i in xrange(100, 130):
param.append([str(i)])
print(param)
cnx = connect_mysql()
cus = cnx.cursor()
print(dir(cus))
try:
cus.execute(sql)
cus.executemany(sql1, param)
# help(cus.executemany)
result1 = cus.fetchone()
print("result1")
print(result1)
result2 = cus.fetchmany(3)
print("result2")
print(result2)
result3 = cus.fetchall()
print("result3")
print(result3)
cus.close()
cnx.commit()
except Exception as e:
cnx.rollback()
raise e
finally:
cnx.close()
python编程中可使用MySQLdb进行数据库的链接及诸如查询/插入/更新等操做,可是每次链接mysql数据库请求时,都是独立的去请求访问,至关浪费资源,并且访问数量达到必定数量时,对mysql的性能会产生较大的影响。所以,实际使用中,一般会使用数据库的链接池技术,来访问数据库达到资源复用的目的。
python的数据库链接池包 DBUtils:
DBUtils是一套Python数据库链接池包,并容许对非线程安全的数据库接口进行线程安全包装。DBUtils来自Webware for Python。
DBUtils提供两种外部接口:
* PersistentDB :提供线程专用的数据库链接,并自动管理链接。
* PooledDB :提供线程间可共享的数据库链接,并自动管理链接。
下载地址:https://pypi.python.org/pypi/DBUtils/ 下载解压后,使用python setup.py install 命令进行安装
或者使用
Pip install DBUtils
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/9/18 22:46
# @Author : lingxiangxiang
# @File : demon4.py
import MySQLdb
from DBUtils.PooledDB import PooledDB
db_config = {
"host": "192.168.48.128",
"port": 3306,
"user": "xiang",
"passwd": "123456",
"db": "python",
"charset": "utf8"
}
pool = PooledDB(MySQLdb, 5, **db_config) # 5为链接池里的最少链接数
conn = pool.connection() # 之后每次须要数据库链接就是用connection()函数获取链接就行了
cur = conn.cursor()
SQL = "select * from tmp;"
r = cur.execute(SQL)
r = cur.fetchall()
print(r)
cur.close()
conn.close()
PooledDB的参数:
1. mincached,最少的空闲链接数,若是空闲链接数小于这个数,pool会建立一个新的链接
2. maxcached,最大的空闲链接数,若是空闲链接数大于这个数,pool会关闭空闲链接
3. maxconnections,最大的链接数,
4. blocking,当链接数达到最大的链接数时,在请求链接的时候,若是这个值是True,请求链接的程序会一直等待,直到当前链接数小于最大链接数,若是这个值是False,会报错,
5. maxshared 当链接数达到这个数,新请求的链接会分享已经分配出去的链接
在uwsgi中,每一个http请求都会分发给一个进程,链接池中配置的链接数都是一个进程为单位的(即上面的最大链接数,都是在一个进程中的链接数),而若是业务中,一个http请求中须要的sql链接数不是不少的话(其实大多数都只须要建立一个链接),配置的链接数配置都不须要太大。
链接池对性能的提高表如今:
1.在程序建立链接的时候,能够从一个空闲的链接中获取,不须要从新初始化链接,提高获取链接的速度
2.关闭链接的时候,把链接放回链接池,而不是真正的关闭,因此能够减小频繁地打开和关闭链接
数据库键表,直接在python代码中执行,
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2017/5/5 13:56
# @Author : lingxiangxiang
# @File : aa.py
import MySQLdb
def connect_mysql():
db_config = {
'host': '192.168.48.128',
'port': 3306,
'user': 'xiang',
'passwd': '123456',
'db': 'python',
'charset': 'utf8'
}
cnx = MySQLdb.connect(**db_config)
return cnx
if __name__ == '__main__':
cnx = connect_mysql()
cus = cnx.cursor()
# sql = '''insert into student(id, name, age, gender, score) values ('1001', 'ling', 29, 'M', 88), ('1002', 'ajing', 29, 'M', 90), ('1003', 'xiang', 33, 'M', 87);'''
student = '''create table Student(
StdID int not null,
StdName varchar(100) not null,
Gender enum('M', 'F'),
Age tinyint
)'''
course = '''create table Course(
CouID int not null,
CName varchar(50) not null,
TID int not null
)'''
score = '''create table Score(
SID int not null,
StdID int not null,
CID int not null,
Grade int not null
)'''
teacher = '''create table Teacher(
TID int not null,
TName varchar(100) not null
)'''
tmp = '''set @i := 0;
create table tmp as select (@i := @i + 1) as id from information_schema.tables limit 10;
'''
try:
cus.execute(student)
cus.execute(course)
cus.execute(score)
cus.execute(thearch)
cus.execute(tmp)
cus.close()
cnx.commit()
except Exception as e:
cnx.rollback()
print('error')
raise e
finally:
cnx.close()
结果:
mysql> show tables;
+------------------+
| Tables_in_python |
+------------------+
| Course |
| Score |
| Student |
| Teacher |
| tmp |
+------------------+
1 rows in set (0.00 sec)
没有任何异常,在数据库中查看表,出现这五个表。说明这五个表已经建立成功。
既然咱们要搞,就尽量的接近实战,咱们来把数据搞大一点,语句设计的复杂一点,这样对咱们之后接触到简单的sql语句时,就有很大的帮助。
首先咱们先来了解一下information_schema这个库,这个在mysql安装时就有了,提供了访问数据库元数据的方式。那什么是元数据库呢?元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等。有些时候用于表述该信息的其余术语包括“数据词典”和“系统目录”。
information_schema数据库表说明:
SCHEMATA表:提供了当前mysql实例中全部数据库的信息。是show databases的结果取之此表。
TABLES表:提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪一个schema,表类型,表引擎,建立时间等信息。是show tables from schemaname的结果取之此表。
COLUMNS表:提供了表中的列信息。详细表述了某张表的全部列以及每一个列的信息。是show columns from schemaname.tablename的结果取之此表。
STATISTICS表:提供了关于表索引的信息。是show index from schemaname.tablename的结果取之此表。
USER_PRIVILEGES(用户权限)表:给出了关于全程权限的信息。该信息源自mysql.user受权表。是非标准表。
SCHEMA_PRIVILEGES(方案权限)表:给出了关于方案(数据库)权限的信息。该信息来自mysql.db受权表。是非标准表。
TABLE_PRIVILEGES(表权限)表:给出了关于表权限的信息。该信息源自mysql.tables_priv受权表。是非标准表。
COLUMN_PRIVILEGES(列权限)表:给出了关于列权限的信息。该信息源自mysql.columns_priv受权表。是非标准表。
CHARACTER_SETS(字符集)表:提供了mysql实例可用字符集的信息。是SHOW CHARACTER SET结果集取之此表。
COLLATIONS表:提供了关于各字符集的对照信息。
COLLATION_CHARACTER_SET_APPLICABILITY表:指明了可用于校对的字符集。这些列等效于SHOW COLLATION的前两个显示字段。
TABLE_CONSTRAINTS表:描述了存在约束的表。以及表的约束类型。
KEY_COLUMN_USAGE表:描述了具备约束的键列。
ROUTINES表:提供了关于存储子程序(存储程序和函数)的信息。此时,ROUTINES表不包含自定义函数(UDF)。名为“mysql.proc name”的列指明了对应于INFORMATION_SCHEMA.ROUTINES表的mysql.proc表列。
VIEWS表:给出了关于数据库中的视图的信息。须要有show views权限,不然没法查看视图信息。
TRIGGERS表:提供了关于触发程序的信息。必须有super权限才能查看该表
而TABLES在安装好mysql的时候,必定是有数据的,由于在初始化mysql的时候,就须要建立系统表,该表必定有数据。
set @i := 0;
create table tmp as select (@i := @i + 1) as id from information_schema.tables limit 10;
mysql中变量不用事前申明,在用的时候直接用“@变量名”使用就能够了。set这个是mysql中设置变量的特殊用法,当@i须要在select中使用的时候,必须加:,这样就建立好了一个表tmp,查看tmp的数据:
mysql> select * from tmp;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+------+
10 rows in set (0.00 sec)
咱们只是从information_schema.tables表中取10条数据,任何表有10条数据也是能够的,而后把变量@i做为id列的值,分10次不断输出,依据最后select的结果,建立表tmp。