首先尝试连接数据库,这里使用PyMySQL连接MySQL,并创建一个新数据库。
#导入pymysql
import pymysql
#使用connect连接
db = pymysql.connect(host='localhost', user='root', password='123456', port=3306)
#调用光标(操作游标)
cursor = db.cursor()
#使用操作游标执行操作,选择版本号
cursor.excute('SELECT VERSION()')
#得到第一条数据,获得版本号
data = cursor.fetchone()
print('Database version:', data)
#创建新数据库,名为spiders
cursion.excute('CREATE DATABASE spiders DEFAULT CHARATER SET utf8')
#关闭
db.close()
'utf8’目前是字符集UTF8MB3的别名,但在将来的版本中将是UTF8MB4的别名。
使用connect()方法声明一个MySQL连接对象时,需要传入host(即IP),本地运行时传入localhost,远程运行时则需要传入其公网IP地址。后续传入用户名,密码,端口(默认3306)。
#导入pymysql
import pymysql
#使用connec连接
db = pymysql.connect(host='localhost', user='root', password='aaasss111', port=3306, db='spiders')
#调用光标(操作游标)
cursor = db.cursor()
#编辑创建语言
sql = 'CREATE TABLE IF NOT EXISTS students (id VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL, age INT NOT NULL, PRIMARY KEY (id))'
#执行创建表
cursor.execute(sql)
#关闭
db.close()
使用not null代表可以允许无值,如果该项没有填入数据,则为空;若设置为null,该项没有填入时,会自动写为null。null可以理解为unknown或者信息缺失的意思。
#导入pymysql
import pymysql
id = '201202020518'
user = 'bob'
age = 25
#使用connec连接
db = pymysql.connect(host='localhost', user='root', password='aaasss111', port=3306, db='spiders')
#调用光标(操作游标)
cursor = db.cursor()
#编辑创建语言
sql = 'INSERT INTO students(id,name, age) values(%s, %s, %s)'
#执行创建表
try:
cursor.execute(sql, (id,user, age))
db.commit()
except:
db.rollback()
#关闭
db.close()
调用commit()方法后,数据的更新,插入,删除才会生效,是使用db调用commit()方法,而不是cursor,cursor仅为光标。
db.rollback()数据回滚,失败的话相当于什么都没有发生,适用于异常处理。
事务的ACID特性:
插入,更新,删除都是对数据库的更改操作,更改操作必须作为一个事务,标准写法:
try:
#执行(使用*光标*操作)
cursor.execute(sql)
#写入(使用*数据库数据库连接对象*操作)
db.commit()
except:
#否则回滚(使用*数据库连接对象*操作)
db.rollback()
动态通用的插入方法
传入一个字典,SQL语句会根据字典动态构造,元组也动态构造,实现通用的插入方法。
#传入一个字典
data = {
'id':'201202020519',
'name': 'sam',
'age': 26
}
#设置各种值
table = 'students'
keys = ', '.join(data.keys())
values = ', '.join(['%s'] * len(data))
#设置一个SQL语句
sql = 'INSERT INTO {table}({keys}) VALUES({values})'.format(table=table, keys=keys,values=values)
#异常处理
try:
#执行SQL语句
if cursor.execute(sql, tuple(data.values())):
print('successful')
#写入
db.commit()
except:
print('failed')
#否则回滚
db.rollback()
#关闭
db.close()
values = ‘, ‘.join([’%s’] * len(data))
使用 len(data)将%s扩展成[%s, %s, %s],如果不加中括号([ ]),结果是%, s, %, s, %,s
最终SQL语句为:INSERT INTO students(id,name,age) VALUES (%s, %s,%s)
更新数据也是执行SQL语句,传入元组形式的参数。
#将name%s的age设置为%s
sql = 'UPDATE students SET age = %s WHERE name = %s'
try:
#执行SQL语句
cursor.execute(sql, (22, 'bob'))
#写入
db.commit()
except:
#否则回滚
db.rollback()
#关闭
db.close()
构造一种新方法,如果数据存在就更新数据,如果不存在就插入数据,可以用来去重。
data = {
'id':'201202020519',
'name': 'sam',
'age': 26
}
#设置一些值
table = 'students'
keys = ', '.join(data.keys())
values = ', '.join(['%s' * len(data)])
#ON DUPLICATE KEY UPDATE表示当主键存在时,执行更新操作
sql = 'INSERT INTO {table}({keys}) VALUES({values}) ON DUPLICATE KEY UPDATE'.format(table=table,
keys=keys,values=values)
#更新
updata = ', '.join(["{key} = %s".format(key=key) for key in data])
#连接起来实现更新数据
sql += updata
try:
if cursor.execute(sql, tuple(data.values()) * 2):
print("successful")
db.commit()
except:
print('failed')
db.rollback()
db.close()
sql += updata构造出来为:
INSERT INTO students(id, name, age) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE id = %s, name = %s, age = %s
当主键(primary key)已经存在时,更新数据而不是插入新数据。
一共有6个%s,所以cursor.execute(sql, tuple(data.values()) * 2)第二个参数需要乘2
直接使用DELETE语句即可,需要指定删除的目标标名称和删除条目,同样需要执行commit()才能生效。
#选择要删除的表
table = 'students'
#设定删除条件
condition = 'age > 20'
#写需要执行的SQL语句
sql = 'DELETE FROM {table} WHERE {condition}'.format(table=table, condition=condition)
#异常处理
try:
#执行SQL语句
cursor.execute(sql)
#写入
db.commit()
except:
#否则回滚
db.rollback()
#关闭
db.close()
删除条件多种多样,运算符有大于,小于,等于,LIKE等,条件连接符有AND, OR等
查询数据需要使用SELECT语句,不需要使用commit()
#设置SQL语句
sql = 'SELECT * FROM students WHERE age >= 20'
#异常处理
try:
#执行SQL语句
cursor.execute(sql)
#获取查询结果的条数
print('Count:', cursor.rowcount)
#fetchone()方法可以获得结果的第一条数据
one = cursor.fetchone()
#可将结果打印
print('One:', one)
#获取所有查询结果
results = cursor.fetchall()
#将所有的查询结果打印
print('Result:', results)
#遍历结果,逐条打印
for row in results:
print(row)
except:
print('error')
最初调用了一次fetchone(),光标会偏移一条,再次读取会读取到下一条数据,所以后面是用fetchall()时,结果会少一条。
可以使用while循环加上fetchone()来获取所有数据。因为使用fetchall()会将结果以元组的形式全部返回,数据量较大的时候,占用资源很多,所以可以改为:
#设置SQL语句
sql = 'SELECT * FROM students WHERE age >= 20'
#异常处理
try:
#执行SQL语句
cursor.execute(sql)
#获取查询结果的条数
print('Count:', cursor.rowcount)
#获取光标当前
row = cursor.fetchone()
#如果光标当前有数据就打印结果并获取下一个数据
while row:
print('Row:', row)
#每次都会移动光标
row = cursor.fetchone()
except:
print('error')
每次循环,光标指针都会偏移一条。