一、基础知识
1.1 支持的数据库
- General Purpose Database Systems
IBM DB2
Firebird (and Interbase)
Informix
Ingres
MySQL
Oracle
PostgreSQL
SAP DB (also known as “MaxDB”)
Microsoft SQL Server
Microsoft Access
Sybase
- Data Warehouse Database Systems
Teradata
IBM Netezza
- Database Systems for Embedding Into Applications
asql
GadFly
SQLite
ThnkSQL
- Record-based Databases
MetaKit
ZODB
BerkeleyDB
KirbyBase
Durus
atop
buzhug
1.2 需要用到的库
- 用python操作不同的数据库需要导入不同的DB-API
- DB-API是一种规范,定义了系列的对象和方法,以便为不同的底层数据库的操作提供规范化的标准。
- 使用DB-API操作数据库的规范化流程:
引入API模块
与数据库建立连接
对数据库进行操作
与数据库断开连接
- 需要注意的是,直接使用DB-API操作数据库的大部分语法与Django操作数据库的语法都不一样。
二、初始化操作
2.1 引入库并建立连接
- 现在大部分个人用户都改用MariaDB了,但是其本质就是mysql,所以安装’MySQL-python’这个插件/框架就OK。
pip install MySQL-python
或者到https://sourceforge.net/projects/mysql-python/
拿对应的版本的包。
2.2 先在腾讯云的虚拟主机上初始化数据库
MariaDB [QIANGGUO]> CREATE DATABASE TESTDB;
Query OK, 1 row affected (0.00 sec)
MariaDB [QIANGGUO]> USE TESTDB
Database changed
MariaDB [TESTDB]> CREATE TABLE EMPLOYEE(FIRST_NAME char(20) not null,LAST_NAME char(20) not null,AGE tinyint,SEX char(10),INCOME int)
-> ;
Query OK, 0 rows affected (0.01 sec)
MariaDB [TESTDB]> GRANT ALL ON EMPLOYEE TO 'username'@'%' identified by 'password';
2.3 用个人办公环境的主机测试,是否能够连同服务器
- 在linux系统上连接:
[root@Tyson'sComputer ~]# mysql -u 'username' -p -h'ip'
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 1803
Server version: 5.5.60-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> show DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| TESTDB |
+--------------------+
2 rows in set (0.02 sec)
MariaDB [(none)]>
- 使用python进行简单测试
# -*- coding:utf-8-*-
import MySQLdb
#打开数据库连接
db = MySQLdb.connect("ip","username","password","TESTDB",charset='utf8')
#使用cursor()方法获取操作游标
cursor = db.cursor()
#使用execute方法执行SQL语句
cursor.execute('SELECT VERSION()')
#使用fetchone()方法获取一条数据
data = cursor.fetchone()
print "DataBase version : %s" % data
# 关闭数据库
db.close()
三、基本用法
3.1 创建数据库
- 使用execute()来执行sql语句。
# -*- coding:utf-8-*-
import MySQLdb
#打开数据库连接
db = MySQLdb.connect("ip","username","password","TESTDB",charset='utf8')
#使用cursor()方法获取操作游标
cursor = db.cursor()
#使用execute方法删除刚才已存在的employee表
cursor.execute('DROP TABLE IF EXISTS EMPLOYEE')
createsql = """CREATE TABLE EMPLOYEE (
FIRST_NAME CHAR(20) NOT NULL,
LAST_NAME CHAR(20),
AGE INT,
SEX CHAR(1),
INCOME FLOAT)"""
cursor.execute(createsql)
# 关闭数据库
db.close()
3.2 数据库插入操作
- 方法1:直接插入值
# -*- coding:utf-8-*-
import MySQLdb
#打开数据库连接
db = MySQLdb.connect("ip","username","password","TESTDB",charset='utf8')
#使用cursor()方法获取操作游标
cursor = db.cursor()
insertsql = """
INSERT INTO EMPLOYEE(FIRST_NAME,LAST_NAME,AGE,SEX,INCOME)
VALUES ('tyson','lee',21,'M',2000)"""
#尝试执行插入语句,成功则提交
#若产生错误则撤销插入操作
try:
cursor.execute(insertsql)
db.commit()
except:
db.rollback()
# 关闭数据库
db.close()
- 方法二:在插入数据时传入变量,一个常见的使用场景就是在传入帐号和密码的时候,值是根据用户的输入而定的。
# -*- coding:utf-8-*-
import MySQLdb
#打开数据库连接
db = MySQLdb.connect("ip","username","password","TESTDB",charset='utf8')
#使用cursor()方法获取操作游标
cursor = db.cursor()
insertsql = "INSERT INTO EMPLOYEE(FIRST_NAME,LAST_NAME,AGE,SEX,INCOME)VALUES ('%s','%s',%s,'%s',%s)" % ('tyson1','lee',22,'M',3000)
print insertsql
#尝试执行插入语句,成功则提交
#若产生错误则撤销插入操作
try:
cursor.execute(insertsql)
db.commit()
except:
db.rollback()
# 关闭数据库
db.close()
- 在这里需要注意,插入数据库的数据的字符串两边需要加上单引号说明,否则是插入不了的。
3.3 数据库查询操作
- 先造一些数据
MariaDB [TESTDB]> select * from EMPLOYEE;
+------------+-----------+------+------+--------+
| FIRST_NAME | LAST_NAME | AGE | SEX | INCOME |
+------------+-----------+------+------+--------+
| tyson1 | lee | 22 | M | 3000 |
| tyson2 | lee | 22 | M | 4000 |
| tyson5 | lee | 22 | M | 4000 |
| tyson6 | lee | 22 | M | 400 |
| tyson7 | lee | 22 | M | 300 |
+------------+-----------+------+------+--------+
5 rows in set (0.02 sec)
- 查询的主要方法
- fetchall():获得所有符合条件的数据集合,以嵌套元组的形式给出。
# -*- coding:utf-8-*-
import MySQLdb
#打开数据库连接
db = MySQLdb.connect("ip","username","password","TESTDB",charset='utf8')
#使用cursor()方法获取操作游标
cursor = db.cursor()
insertsql = "SELECT * FROM EMPLOYEE WHERE INCOME > %s" % (1000)
#尝试执行插入语句,成功则提交
#若产生错误则撤销插入操作
try:
cursor.execute(insertsql)
#用fetchall拿到由多行记录组成的数据集
results = cursor.fetchall()
print results
for row in results:
fname = row [0]
lname = row [1]
age = row[2]
sex = row[3]
income = row[4]
print "fname=%s,lname=%s,age=%s,sex=%s,income=%s" % (fname,lname,age,sex,income)
except:
print "Error:unable to fetch data"
# 关闭数据库
db.close()
result:
((u'tyson1', u'lee', 22L, u'M', 3000.0), (u'tyson2', u'lee', 22L, u'M', 4000.0), (u'tyson5', u'lee', 22L, u'M', 4000.0))
fname=tyson1,lname=lee,age=22,sex=M,income=3000.0
fname=tyson2,lname=lee,age=22,sex=M,income=4000.0
fname=tyson5,lname=lee,age=22,sex=M,income=4000.0
- fetchone():利用fetone()方法每次拿代表一行的元组,类似于生成器
# -*- coding:utf-8-*-
import MySQLdb
#打开数据库连接
db = MySQLdb.connect("ip","username","password","TESTDB",charset='utf8')
#使用cursor()方法获取操作游标
cursor = db.cursor()
insertsql = "SELECT * FROM EMPLOYEE WHERE INCOME > %s" % (1000)
#尝试执行插入语句,成功则提交
#若产生错误则撤销插入操作
try:
cursor.execute(insertsql)
#利用fetone()方法每次拿代表一行的元组,类似于生成器
result = cursor.fetchone()
result1 = cursor.fetchone()
result2 = cursor.fetchone()
print result,result1,result2
except:
print "Error:unable to fetch data"
# 关闭数据库
db.close()
- rowcount:只读属性,返回执行了execute()方法后受到影响的行数。
# -*- coding:utf-8-*-
import MySQLdb
#打开数据库连接
db = MySQLdb.connect("ip","username","password","TESTDB",charset='utf8')
#使用cursor()方法获取操作游标
cursor = db.cursor()
insertsql = "SELECT * FROM EMPLOYEE WHERE INCOME > %s" % (1000)
#尝试执行插入语句,成功则提交
#若产生错误则撤销插入操作
try:
cursor.execute(insertsql)
# 用rowcount拿到执行execute()方法后收到影响的行数
count = cursor.rowcount
print count
except:
print "Error:unable to fetch data"
# 关闭数据库
db.close()
3.3 数据库更新操作
- 定义并执行对应的SQL语句即可,没有特别的方法。
- 当游标建立的时候,就已经产生了隐形的SQL事务,为了保证数据库的ACID特性,在涉及到更改数据库中数据库的操作的时候,要充分利用commit()和rollback()。
- 每一个方法都开始了一个新的事物,直到遇到commit结束。
- 一个事务内的操作要么全部都执行,要么全部都不执行。
# -*- coding:utf-8-*-
import MySQLdb
#打开数据库连接
db = MySQLdb.connect("ip","username","password","TESTDB",charset='utf8')
#使用cursor()方法获取操作游标
updatesql = "UPDATE EMPLOYEE SET INCOME = 50000 WHERE FIRST_NAME = '%s'"%("tyson2")
selectsql = "SELECT * FROM EMPLOYEE WHERE FIRST_NAME = '%s'" % ('tyson2')
#尝试执行插入语句,成功则提交
#若产生错误则撤销插入操作
cursor = db.cursor()
try:
cursor.execute(updatesql)
db.commit()
print "成功更新数据"
except:
db.rollback()
print "更新数据错误"
try:
cursor.execute(selectsql)
result = cursor.fetchone()
print result
except:
print "无法查询到数据"
# 关闭数据库
db.close()`enter code here`
3.4 数据库删除操作
# -*- coding:utf-8-*-
import MySQLdb
#打开数据库连接
db = MySQLdb.connect("ip","username","password","TESTDB",charset='utf8')
#使用cursor()方法获取操作游标
cursor = db.cursor()
deletesql = "DELETE FROM EMPLOYEE WHERE FIRST_NAME = '%s'" % 'tyson2'
selectsql = "SELECT * FROM EMPLOYEE"
#尝试执行删除语句,成功则提交
#若产生错误则撤销插入操作
try:
cursor.execute(deletesql)
db.commit()
print "删除成功"
except:
db.rollback()
try:
cursor.execute(selectsql)
results = cursor.fetchall()
for row in results:
print row
except:
print "查询数据失败"
# 关闭数据库
db.close()
result:
删除成功
(u'tyson1', u'lee', 22L, u'M', 3000.0)
(u'tyson5', u'lee', 22L, u'M', 4000.0)
(u'tyson6', u'lee', 22L, u'M', 400.0)
(u'tyson7', u'lee', 22L, u'M', 300.0)
四、mysql的事务性
- 事务机制是为了防止同时有多个进程在对数据库的数据进行更改而导致的数据库数据不准确的错误。
- 事务拥有四个属性:ACID、也就是原子性、一致性、隔离性、持久性。
- 原子性:automicity,事务是不可分割的单位,事务里面的语句要么全做,要么全都不做。
- 一致性:consistency
- 隔离性:不同的事务之间无法相互干扰。
- 永久性:事务一旦提交就不可更改。
- 两种开始事务的方法:
- 当游标(cursor)建立的时候,就开始了一个隐藏的数据库事务。
- 每个方法都开始了一个新的数据库事务。
- 两个方法:
- commit()提交所有更新操作
- rollback()回滚当前游标所有已进行的操作
五、数据库错误的处理
异常 | 描述 |
---|---|
Warning | 当有严重警告时触发,例如插入数据是被截断等等。必须是 StandardError 的子类。 |
Error | 警告以外所有其他错误类。必须是 StandardError 的子类。 |
InterfaceError | 当有数据库接口模块本身的错误(而不是数据库的错误)发生时触发。 必须是Error的子类。 |
DatabaseError | 和数据库有关的错误发生时触发。 必须是Error的子类。 |
DataError | 当有数据处理时的错误发生时触发,例如:除零错误,数据超范围等等。 必须是DatabaseError的子类。 |
OperationalError | 指非用户控制的,而是操作数据库时发生的错误。例如:连接意外断开、 数据库名未找到、事务处理失败、内存分配错误等等操作数据库是发生的错误。 必须是DatabaseError的子类。 |
IntegrityError | 完整性相关的错误,例如外键检查失败等。必须是DatabaseError子类。 |
InternalError | 数据库的内部错误,例如游标(cursor)失效了、事务同步失败等等。 必须是DatabaseError子类。 |
ProgrammingError | 程序错误,例如数据表(table)没找到或已存在、SQL语句语法错误、 参数数量错误等等。必须是DatabaseError的子类。 |
NotSupportedError | 不支持错误,指使用了数据库不支持的函数或API等。例如在连接对象上 使用.rollback()函数,然而数据库并不支持事务或者事务已关闭。 必须是DatabaseError的子类。 |