〇、使用数据库驻留连接池
数据库驻留连接池是 Oracle Database 11g 的一个新特性。它对 Web 应用程序常用的短期脚本非常有用。它允许随着 Web 站点吞吐量的增长对连接数量进行扩充。它还支持多台计算机上的多个 Apache 进程共享一个小规模的数据库服务器进程池。没有 DRCP,Python 连接必须启动和终止一个服务器进程。
所有脚本都可使用来自服务器池的数据库服务器,不再需要时将退回服务器。
一、Oracle 简单查询
查询的基础始终是相同的:
1. 分析要执行的语句。
2. 绑定数据值(可选)。
3. 执行语句。
4. 从数据库中获取结果。importcx_Oracle
con=cx_Oracle.connect('pythonhol/welcome@127.0.0.1/orcl')
cur=con.cursor()#cursor() 方法打开语句要使用的游标。
cur.execute('select * from departments order by department_id') #execute() 方法分析并执行语句。
for result in cur: #循环从游标获取每一行并输出该行。
print result
cur.close()
con.close()
二、Oracle 获取数据
从 Oracle 数据库中获取数据的方式有多种
1)使用cursor.fetchone()方法importcx_Oracle
con=cx_Oracle.connect('pythonhol/welcome@127.0.01/orcl')
cur=con.cursor()
cur.execute('select * from departments order by department_id')
row=cur.fetchone()# fetchone() 方法只返回一行作为一个字节组
print row
row = cur.fetchone() # 多次调用该方法后,返回连续的多行
print row
cur.close()
con.close()
执行完毕后,两次 fetchone() 调用输出两条记录
2)使用cursor.fetchmany()方法importcx_Oracle
con=cx_Oracle.connect('pythonhol/welcome@127.0.0.1/orcl')
cur=con.cursor()
cur.execute('select * from departments order by department_id')
res=cur.fetchmany(numRows=3)#返回一个字节组列表,numRows 参数指定应返回三行
print res
cur.close()
con.close()
执行完毕后,以字节组列表形式返回了表的头三行
3)使用cursor.fetchall()方法importcx_Oracle
con=cx_Oracle.connect('pythonhol/welcome@127.0.0.1/orcl')
cur=con.cursor()
cur.execute('select * from departments order by department_id')
res=cur.fetchall()#返回所有行
print res #输出是一个字节组列表,每个字节组包含一行的数据
forrinres:#每个字节组分别输出,选择使用哪种获取方法主要取决于您希望如何处理返回的数据
print r
cur.close()
con.close()
三、提高查询性能
通过增加每批从 Oracle 返回到 Python 程序的行数来提高查询性能的方法。importtime
import cx_Oracle
con=cx_Oracle.connect('pythonhol/welcome@127.0.0.1/orcl')
start=time.time()
cur=con.cursor()
cur.arraysize=100#每次从数据库向 Python 的缓存返回 100 条记录
cur.execute('select * from bigtab')
res = cur.fetchall()
# print res # uncomment to display the query results
elapsed = (time.time() - start)
print elapsed, " seconds"
cur.close()
con.close()
cursor.arraysize 合理设置,可以减少对数据库的“往返”次数,通常还会降低网络负载并减少数据库服务器上下文切换次数
从数据库请求更多的数据之前,fetchone()、fetchmany()、甚至 fetchall() 方法都将从缓存读取数据。
要增加 arraysize,需要在时间/空间方面进行权衡。arraysizes 越大,Python 中用于缓存记录需要的内存也越大。
四、使用绑定变量
绑定变量允许您使用新值重新执行语句,避免了重新分析语句的开销。绑定变量提高了代码可重用性,降低了 SQL 注入攻击的风险。importcx_Oracle
con=cx_Oracle.connect('pythonhol/welcome@127.0.0.1/orcl')
cur=con.cursor()
cur.prepare('select * from departments where department_id = :id')#绑定变量前的准备
cur.execute(None, {'id': 210}) #第一次绑定变量执行,通过 python 字典的方式进行传参
res = cur.fetchall()
print res
cur.execute(None, {'id': 110}) #第二次绑定变量执行
res = cur.fetchall()
print res
cur.close()
con.close()
该语句包含一个绑定变量“:id”。该语句只准备了一次,但针对 WHERE 子句的不同值执行了两次。
因为 prepare() 方法已经对该语句进行了设置,因此对 execute() 使用特殊符号“None”代替该语句的文本参数。
cx_Oracle 驱动程序支持 INSERT 语句的数组绑定,这样可以大大提高单行插入的性能。importcx_Oracle
con=cx_Oracle.connect('pythonhol/welcome@127.0.0.1/orcl')
rows=[(1,"First"),
(2,"Second"),
(3,"Third"),
(4,"Fourth"),
(5,"Fifth"),
(6,"Sixth"),
(7,"Seventh")]
cur=con.cursor()
cur.bindarraysize=7# bindarraysize 设置为 7,意味着一次就插入全部七行
cur.setinputsizes(int, 20) # setinputsizes() 调用描述了列的情况,第一列是整数。第二列最多为 20 个字节
cur.executemany("insert into mytab(id, data) values (:1, :2)", rows) #调用插入全部七行。
#con.commit() #commit() 调用被注释掉了,因此不会真正被插入数据库中
# Now query the results back
cur2 = con.cursor() #当执行第二次查询的时候,新建了一个游标
cur2.execute('select * from mytab')
res = cur2.fetchall()
print res
cur.close()
cur2.close()
con.close()
五、创建事务
在 Oracle 数据库中操作数据(插入、更新或删除数据)时,更改的数据或新数据在提交至数据库前仅在数据库会话中可用。更改的数据提交至数据库,然后可供其他用户和会话使用。这是一个数据库事务。importcx_Oracle
con=cx_Oracle.connect('pythonhol/welcome@127.0.0.1/orcl')
rows=[(1,"First"),
(2,"Second"),
(3,"Third"),
(4,"Fourth"),
(5,"Fifth"),
(6,"Sixth"),
(7,"Seventh")]
cur=con.cursor()
cur.bindarraysize=7
cur.setinputsizes(int,20)
cur.executemany("insert into mytab(id, data) values (:1, :2)",rows)
con.commit()#commit() 是针对连接执行,而非针对游标,因此前面使用的是数据库连接的对象
# Now query the results back
cur2 = con.cursor()
cur2.execute('select * from mytab')
res = cur2.fetchall()
print res
cur.close()
cur2.close()
con.close()
如果需要在脚本中启动回滚,则可使用 con.rollback() 方法。
六、使用 PL/SQL 存储函数和过程
PL/SQL 是 Oracle 对 SQL 的过程语言扩展。PL/SQL 过程和函数在数据库中存储和运行。使用 PL/SQL 允许所有数据库应用程序重用逻辑,无论应用程序以何种方式访问数据库。许多与数据相关的操作在 PL/SQL 中的执行速度比将数据提取到一个程序中(例如,Python)然后再进行处理的速度快。Oracle 还支持 Java 存储过程。importcx_Oracle
con=cx_Oracle.connect('pythonhol/welcome@127.0.0.1/orcl')
cur=con.cursor()
res=cur.callfunc('myfunc',cx_Oracle.NUMBER,('abc',2))
printres
cur.close()
con.close()
该脚本使用 callfunc() 执行此函数。常量 cx_oracle.NUMBER 指示返回值是数字。PL/SQL 函数的两个参数作为一个字节组传输并绑定到该函数的参数。
要调用 PL/SQL 过程,使用 cur.callproc() 方法。
七、连续查询通知
连续查询通知(也称为数据库更改通知)允许应用程序在表更改时(例如,向表中插入行)接收通知。在许多情况下这一功能非常有用,包括中间层缓存无效的情况。缓存可能会容纳一些与表数据有依赖关系的值。如果表发生更改,缓存的值也必须按照新信息进行更新。