Python 中将数据保存到数据库中技术有很多,但主要分为两类:遵循Python DB-API 规范技术(Python Database API Specification) 和ORM 技术(Object-Relational mapping) 。Python DB-API 规范通过在Python 中编写SQL 语句访问数据库。ORM 技术是面向对象的,对数据的访问是通过对象实现的,程序员不需要使用SQL 语句。
在Python2.X 中操作MySQL 数据库可以通过Pyhon 的MySQLdb 模块实现,由于目前Python3.5 不支持MySQLdb 模块,所以我们使用pymysql 模块。
下面介绍数据库的基本操作步骤:
==1. 创建数据库连接==
import pymysql
#连接数据库
conn = pymysql.connect(
host=‘localhost‘, # 数据库主机名或IP
port=3306 # 连接数据库端口号
user=‘root‘, # 访问数据库帐号
password=‘1234‘, # 访问数据库密码
database=‘mydatabase‘, # 数据库中的库名
charset=‘utf8‘) # 数据库编码格式
Connection 对象有一些重要的方法 : close() :
关闭数据库连接,关闭之后再使用数据库连接将引发异常。 commit() :
提交数据库事务。 rollback() :
回滚数据库事务。 cursor() :
获得Cursor 游标对象。
==2. 创建游标==
一个Cursor 游标对象表示一个数据库游标,游标暂时保存了SQL 操作所影响到的数据。 在数据库事务管理中游标非常重要,游标是通过数据库连接创建的,相同数据库连接创 建的游标所引起的数据变化,会马上反映到同一连接中的其他游标对象。但是不同数据 库连接中的游标,是否能及时反映出来,则与数据库事务管理有关。
游标Cursor 对象方法: 1.execute(operation[, parameters])
执行一条SQL 语句,operation 是SQL 语句,parameters 是为SQL 提供的参数,可以是 序列或 字典 类型。返回值是整数,表示执行SQL 语句影响的行数。 2. executemany(operation[, seq_of_params])
执行批量SQL 语句,operation 是SQL 语句,seq_of_params 是为SQL 提供的参数, seq_of_params 是 序列 。返回值是整数,表示执行SQL 语句影响的行数。 3.callproc(procname[, parameters])
执行存储过程,procname 是存储过程名,parameters 是为存储过程提供的参数。 4.fetchone()
从结果集中返回一条记录的序列,如果没有数据返回None 。 5.fetchmany([size=cursor.arraysize)
从结果集中返回小于或等于size 的记录数序列,如果没有数据返回空序列,size 默认情况下是整个游标的行数。 6.fetchall()
从结果集中返回所有数据。
实列:
1. 创建数据库:
import pymysql
# 连接数据库
conn = pymysql.connect(
host=‘127.0.0.1‘,
port=3306,
user=‘root‘,
password=‘1234‘,
charset=‘utf8‘
)
cursor = conn.cursor() # 拿到游标
cursor.execute("create database if not exists mydatabase") # 创建数据库
cursor.close() # 关闭游标
conn.close() # 关闭连接
2. 创建数据库表:
import pymysql
# 连接数据库
conn = pymysql.connect(
host=‘127.0.0.1‘,
port=3306,
user=‘root‘,
password=‘1234‘,
db=‘mydatabase‘,
charset=‘utf8‘
)
cursor = conn.cursor() # 拿到游标
cursor.execute(‘‘‘create table if not exists student (
number varchar(20) primary key,
name varchar(50) not null,
sex varchar(2) check (sex in(‘M’,‘F’)),
math double(4,1),
english double(4,1),
computer double(4,1)
‘‘‘)
cursor.close()
conn.close()
3. 插入数据:
import pymysql
# 1. 创建数据库连接
conn = pymysql.connect(
host=‘127.0.0.1‘,
port=3306,
user=‘root‘,
password=‘1234‘,
db=‘mydatabase‘
charset=‘utf8‘
)
try:
# 2. 创建游标对象
with conn.cursor() as cursor: #with 代码块结束时就会关闭游标对象。
# 3. 执行sql 操作。插入多条语句
sql = ‘insert into student(number, name, sex, math, english, computer) values (%s, %s, %s, %s, %s, %s)‘
data = [
(‘1501‘, ‘ 炎黄‘, ‘M‘, 78.5, 70.0, 100.0),
(‘1505‘, ‘ 吕萌萌‘, ‘M‘, 100.0, 90.0, 95.0),
(‘1509‘, ‘ 石耀举‘, ‘F‘, 60.5, 90.0, 70.0)
]
cursor.executemany(sql, data)
# 3. 执行sql 操作 。插入 单条 数据
data = (‘1521‘, ‘ 王维‘, ‘F‘, 68.4, 73.0, 55.0)
cursor.execute(sql, data) # 参数放在列表中,或放在元组中
# 4. 提交数据库事务
conn.commit()
# with 代码块结束 5. 自动关闭游标
except pymysql.DatabaseError:
conn.rollback() # 4. 回滚数据库事务
finally:
conn.close()# 6. 关闭数据库连接
4. 删除数据
import pymysql
# 1. 创建数据库连接
conn = pymysql.connect(
host=‘127.0.0.1‘,
port=3306,
user=‘root‘,
password=‘1234‘,
db=‘mydatabase‘
charset=‘utf8‘
)
try:
# 2. 创建游标对象
with conn.cursor() as cursor:
# 3. 执行sql 语句
sql = ‘delete from student where number=%s‘
cursor.execute(sql, ‘1502‘)
cursor.executemany(sql, (‘1505‘, ‘1507‘, ‘1514‘))
# 4. 提交数据库事务
conn.commit()
# with 代码块结束 5. 关闭游标
except pymysql.DatabaseError:
conn.rollback()# 4. 回滚数据库事务
finally:
conn.close()# 6. 关闭数据库连接
5. 修改数据
import pymysql
# 1. 创建数据库连接
conn = pymysql.connect(
host=‘127.0.0.1‘,
port=3306,
user=‘root‘,
password=‘1234‘,
db=‘mydatabase‘
charset=‘utf8‘
)
try:
#2. 创建游标对象
with conn.cursor() as cursor:
# 3. 执行sql 语句
sql = ‘update student set name=%s where number > %s‘
cursor.execute(sql, (‘ 水份‘, ‘1510‘))
# 4. 提交数据库事务
conn.commit()
# with 代码块结束 5. 关闭游标
except pymysql.DatabaseError:
# 4. 回滚数据库事务
conn.rollback()
finally:
# 6. 关闭数据库连接
conn.close()
6. 查找数据
import pymysql
# 1. 创建数据库连接
conn = pymysql.connect(
host=‘127.0.0.1‘,
port=3306,
user=‘root‘,
password=‘1234‘,
db=‘mydatabase‘
charset=‘utf8‘
)
try:
# 2. 创建游标对象
with conn.cursor() as cursor:
# 3. 执行sql 操作
sql = ‘select * from student‘
cursor.execute(sql)
# 4. 提取结果集
# 提取所有数据,返回结果默认是元组形式,所以可以进行迭代处理
result_list = cursor.fetchall()
for row in result_list:
print(row)
print(‘ 共查询到:‘, cursor.rowcount, ‘ 条数据。‘)
# 4. 提取结果集。获取第一行数据
result1 = cursor.fetchone()
print(result1)
# 4. 提取结果集。获取前n 行数据
result2 = cursor.fetchmany(2)
print(result2)
# with 代码块结束 5. 关闭游标
finally:
# 6. 关闭数据库连接
conn.close()
7. 数据库配置文件的使用
配置文件configparser.ini
[db]
host = 127.0.0.1
port = 3306
user = root
password = 1234
database = mydatabase
charset = utf8
import pymysql
import configparser
config = configparser.ConfigParser()
config.read(‘config.ini‘, encoding=‘utf-8‘)
host = config[‘db‘][‘host‘]
port = config.getint(‘db‘, ‘port‘)
user = config[‘db‘][‘user‘]
password = config[‘db‘][‘password‘]
database = config[‘db‘][‘database‘]
charset = config[‘db‘][‘charset‘]
# 1. 创建数据库连接
conn = pymysql.connect(
host=host,
port=port,
user=user,
password=password,
database=database,
charset=charset
)
cursor 就是一个Cursor 对象,这个cursor 是一个实现了迭代器和生成器的对象,这个时候cursor 中还没有数据,只有等到fetchone() 或fetchall() 的时候才返回一个元组tuple ,才支持len() 和index() 操作,这也是它是迭代器的原因 。但同时为什么说它是生成器呢?因为cursor 只能用一次,即每用完一次之后记录其位置,等到下次再取的时候是从游标处再取而不是从头再来,而且fetch 完所有的数据之后,这个cursor 将不再有使用价值了,即不再能fetch 到数据了。
8. 学生管理系统
import pymysql
import wx
import wx.grid
class MyData():
def __init__(self):
self.tableText=["number","name","sex","math","english","computer"]
self.mydata=[]
self.conn = pymysql.connect(
host="127.0.0.1",
port=3306,
user="root",
password="123456",
database="student",
charset="utf8"
)
def Conn(self):
self.conn = pymysql.connect(
host="127.0.0.1",
port=3306,
user="root",
password="123456",
database="student",
charset="utf8"
)
def showData(self,number):
self.Conn()
try:
with self.conn.cursor() as cursor:
self.mydata=[]
if number=="":
sqlstr = "select * from test1"
cursor.execute(sqlstr, ())
else:
sqlstr = "select * from test1 where number=%s"
cursor.execute(sqlstr, (number))
result_list=cursor.fetchall()
for item in result_list:
print(item)
self.mydata.append(item)
except pymysql.DatabaseError:
self.conn.rollback()
finally:
self.conn.close()
def insterData(self,data):
self.Conn()
try:
with self.conn.cursor() as cursor:
sqlstr = """
insert into test1 (number,name,sex,math,english,computer)
values(%s,%s,%s,%s,%s,%s)
"""
cursor.execute(sqlstr, data)
self.conn.commit()
except pymysql.DatabaseError:
self.conn.rollback()
finally:
self.conn.close()
def uptateData(self,data):
self.Conn()
try:
with self.conn.cursor() as cursor:
sqlstr = "update test1 set number=%s,name= %s ,sex=%s,math=%s,english=%s,computer=%s where number=%s"
cursor.execute(sqlstr, data)
self.conn.commit()
except pymysql.DatabaseError:
self.conn.rollback()
finally:
self.conn.close()
def deleteData(self,number):
self.Conn()
try:
with self.conn.cursor() as cursor:
sqlstr = "delete from test1 where number=%s"
print(number)
cursor.execute(sqlstr, number)
self.conn.commit()
except pymysql.DatabaseError:
self.conn.rollback()
finally:
self.conn.close()
def colse(self):
self.conn.close()
class MyGridTable(wx.grid.GridTableBase):
def __init__(self,tableText,data):
super().__init__()
self.tableText=tableText
self.data=data
self.colLabels=tableText
def GetNumberRows(self):
return len(self.data)
def GetNumberCols(self):
return len(self.tableText)
def GetValue(self, row, col):
return self.data[row][col]
def GetColLabelValue(self, col):
return self.tableText[col]
class AddorChangeFrame(wx.Frame):
def __init__(self,frame):
if frame=="添加":
super().__init__(parent=None,size=(300,350),title="添加")
else:
super().__init__(parent=None, size=(300, 350), title="修改")
self.Center()
panel=wx.Panel(self)
number=wx.StaticText(parent=panel,id=-1,label="学号")
self.numbertext=wx.TextCtrl(parent=panel,id=-1)
box1=wx.BoxSizer()
box1.Add(number)
box1.Add(self.numbertext)
name = wx.StaticText(parent=panel, id=-1, label="姓名")
self.nametext = wx.TextCtrl(parent=panel, id=-1)
box2 = wx.BoxSizer()
box2.Add(name)
box2.Add(self.nametext)
sex = wx.StaticText(parent=panel, id=-1, label="性别")
self.sextext = wx.TextCtrl(parent=panel, id=-1)
box3 = wx.BoxSizer()
box3.Add(sex)
box3.Add(self.sextext)
math = wx.StaticText(parent=panel, id=-1, label="数学")
self.mathtext = wx.TextCtrl(parent=panel, id=-1)
box4 = wx.BoxSizer()
box4.Add(math)
box4.Add(self.mathtext)
english = wx.StaticText(parent=panel, id=-1, label="英语")
self.englishtext = wx.TextCtrl(parent=panel, id=-1)
box5 = wx.BoxSizer()
box5.Add(english)
box5.Add(self.englishtext)
computer = wx.StaticText(parent=panel, id=-1, label="学号")
self.computertext = wx.TextCtrl(parent=panel, id=-1)
box6 = wx.BoxSizer()
box6.Add(computer)
box6.Add(self.computertext)
if frame=="添加":
button1 = wx.Button(parent=panel, id=2, label="添加")
else:
button1=wx.Button(parent=panel,id=3,label="修改")
button2 = wx.Button(parent=panel, id=1, label="取消")
self.Bind(wx.EVT_BUTTON, self.on_button, id=1, id2=3)
box7=wx.BoxSizer()
box7.Add(button1)
box7.Add(button2)
mainbox=wx.BoxSizer(wx.VERTICAL)
mainbox.Add(box1,1,flag=wx.ALL,border=5)
mainbox.Add(box2,1,flag=wx.ALL,border=5)
mainbox.Add(box3,1,flag=wx.ALL,border=5)
mainbox.Add(box4,1,flag=wx.ALL,border=5)
mainbox.Add(box5,1,flag=wx.ALL,border=5)
mainbox.Add(box6,1,flag=wx.ALL,border=5)
mainbox.Add(box7, 1, flag=wx.ALL, border=5)
panel.SetSizer(mainbox)
def on_button(self, event):
id = event.GetId()
number=self.numbertext.GetValue()
name = self.nametext.GetValue()
sex = self.sextext.GetValue()
math = self.mathtext.GetValue()
english=self.englishtext.GetValue()
computer = self.computertext.GetValue()
data = MyData()
# 取消
if id == 1:
self.Close()
# 添加
elif id==2:
data.insterData((number, name, sex, math, english, computer))
self.Close()
# 修改
else:
data.uptateData((number, name, sex, math, english, computer,number))
self.Close()
class myFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,size=(700,400),title="学生信息管理系统")
self.Center()
panel=wx.Panel(self)
box1=wx.BoxSizer(wx.HORIZONTAL)
text1=wx.StaticText(parent=panel,id=-1,label="请输入学号:")
self.inputtext=wx.TextCtrl(parent=panel,id=-1)
findbutton=wx.Button(parent=panel,id=1,label="查询")
deletebutton = wx.Button(parent=panel, id=4, label="删除")
self.Bind(wx.EVT_BUTTON,self.on_button,id=1,id2=4)
b = wx.BoxSizer(wx.HORIZONTAL)
b.Add(text1,1,flag=wx.LEFT|wx.TOP|wx.BOTTOM,border=15)
b.Add(self.inputtext, 1,flag=wx.ALL,border=10)
b.Add(findbutton, 1,flag=wx.ALL,border=10)
b.Add(deletebutton, 1, flag=wx.ALL, border=10)
box1.Add(b,1,flag=wx.LEFT|wx.RIGHT,border=70)
self.grid = wx.grid.Grid(parent=panel,size=(580,255))
rowsizeinfo=wx.grid.GridSizesInfo(40,[])
self.grid.SetRowSizes(rowsizeinfo)
data=MyData()
data.showData("")
table = MyGridTable(data.tableText,data.mydata)
self.grid.SetTable(table, True)
box2 = wx.BoxSizer()
box2.Add(self.grid)
addbutton = wx.Button(parent=panel, id=2, label="添加")
updatebutton = wx.Button(parent=panel, id=3, label="修改")
box3 = wx.BoxSizer()
box3.Add(addbutton,1,flag=wx.EXPAND)
box3.Add(updatebutton, 1, flag=wx.EXPAND)
mainbox = wx.BoxSizer(wx.VERTICAL)
mainbox.Add(box1,1,flag=wx.EXPAND)
mainbox.Add(box2, 1,flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=50)
mainbox.Add(box3, 1,flag=wx.EXPAND)
panel.SetSizer(mainbox)
def on_button(self, event):
id = event.GetId()
data = MyData()
if id == 1:
data.showData(self.inputtext.GetValue())
print("查询!!!")
elif id==2:
print("添加!!!")
self.addFrame=AddorChangeFrame("添加")
self.addFrame.Show()
elif id == 3:
self.addFrame = AddorChangeFrame("修改")
self.addFrame.Show()
print(