原文:https://www.cnblogs.com/xiao-apple36/p/9066980.html#_label6
参照文档
http://www.oracle.com/technetwork/cn/articles/dsl/mastering-oracle-python-1391323-zhs.html
http://cx-oracle.readthedocs.io/en/latest/module.html
回到顶部Python 数据库 API 规范 v2.0 是集体努力的成果,用于统一不同数据库系统的访问模型。拥有一组相对较少的方法和属性,在更换数据库供应商时就易于学习并保持一致。它不以任何方式将数据库对象映射到 Python 结构中。用户仍然需要手工编写 SQL。在更换到另一数据库后,此 SQL 可能需要重新编写。尽管如此,它还是出色妥善地解决了 Python 数据库的连接性问题。
该规范定义了 API 的各个部分,如模块接口、连接对象、游标对象、类型对象和构造器、DB API 的可选扩展以及可选的错误处理机制。
数据库和 Python 语言之间的网关是连接对象。它包含制作数据库驱动的应用程序所需的全部组件,不仅符合 DB API 2.0,而且是规范方法和属性的一个超集。在多线程的程序中,模块和连接可以在不同线程间共享,但是不支持游标共享。这一限制通常是可接受的,因为共享游标可能带来死锁风险。
Python 大量使用了异常模型,DB API 定义了若干标准异常,它们在调试应用程序中的问题时会非常有用。下面是一些标准异常,同时提供了原因类型的简要说明:
连接过程首先从连接对象开始,这是创建游标对象的基础。除游标操作外,连接对象还使用 commit() 和 rollback() 方法对事务进行管理。执行 SQL 查询、发出 DML/DCL 语句和获取结果这些过程均受游标控制。
回到顶部
>>> import cx_Oracle >>> db = cx_Oracle.connect('hr', 'hrpwd', 'localhost:1521/XE') >>> db1 = cx_Oracle.connect('hr/hrpwd@localhost:1521/XE') >>> dsn_tns = cx_Oracle.makedsn('localhost', 1521, 'XE') >>> print dsn_tns (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SID=XE))) >>> db2 = cx_Oracle.connect('hr', 'hrpwd', dsn_tns)
# 通过客户端连接oracle
connection = cx_Oracle.connect('test/test@ORCL')
回到顶部
您可以使用连接对象的 cursor() 方法定义任意数量的游标。简单的程序使用一个游标就可以了,该游标可以一再地重复使用。但较大的项目可能要求几个不同的游标。
>>> cursor = db.cursor()
应用程序逻辑通常需要明确区分针对数据库发出的语句的各个处理阶段。这有助于更好地理解性能瓶颈并编写更快且经过优化的代码。语句处理分三个阶段:
在继续了解游标示例前,请先了解 pprint 模块的 pprint 函数。它用于以清晰、可读的形式输出 Python 数据结构。
# 获得游标对象 cursor = connection.cursor () try: # 解析sql语句 cursor.parse("select * dual") # 捕获SQL异常 except cx_Oracle.DatabaseError as e: print(e) # ORA-00923: 未找到要求的 FROM 关键字 # 执行sql 语句 cursor.execute ("select * from dual") # 提取一条数据,返回一个元祖 row = cursor.fetchone() pprint(row) # ('X',)
回到顶部
在获取阶段,基本的 Oracle 数据类型会映射到它们在 Python 中的等同数据类型中。cx_Oracle 维护一个单独的、有助于这一转换的数据类型集合。Oracle - cx_Oracle - Python 映射为
查询列字段信息
# 查询列字段信息 column_data_types = cursor.execute('SELECT * FROM python_modules') pprint(column_data_types.description) # [('MODULE_NAME', <class 'cx_Oracle.STRING'>, 50, 50, None, None, 0), # ('FILE_PATH', <class 'cx_Oracle.STRING'>, 300, 300, None, None, 0)]
回到顶部
正如 Oracle 大师 Tom Kyte 介绍的那样,绑定变量是数据库开发的核心原则。它们不仅使程序运行更快,同时可以防范 SQL 注入攻击。
按名称传递绑定变量要求执行方法的 parameters 参数是一个字典或一组关键字参数。下面的 query1 和 query2 是等同的: >>> named_params = {'dept_id':50, 'sal':1000} >>> query1 = cursor.execute('SELECT * FROM employees WHERE department_id=:dept_id AND salary>:sal', named_params) >>> query2 = cursor.execute('SELECT * FROM employees WHERE department_id=:dept_id AND salary>:sal', dept_id=50, sal=1000) 在使用已命名的绑定变量时,您可以使用游标的 bindnames() 方法检查目前已指定的绑定变量: >>> print cursor.bindnames() ['DEPT_ID', 'SAL'] # 绑定变量模式查询 named_params = {'MODULE_NAME': 'cx_Oracle'} cursor.execute('SELECT * FROM python_modules where MODULE_NAME =:MODULE_NAME',named_params) # 在使用已命名的绑定变量时,您可以使用游标的 bindnames() 方法检查目前已指定的绑定变量: print(cursor.bindnames()) pprint(cursor.fetchone()) # ('cx_Oracle', # 'C:\Program ' # 'Files\Python36\lib\site-packages\cx_Oracle.cp36-win_amd64.pyd') # 在绑定时,您可以首先准备该语句,然后利用改变的参数执行 None。 # 根据绑定变量时准备一个语句即足够这一原则, # Oracle 将如同在上例中一样对其进行处理。准备好的语句可执行任意次。 cursor.prepare('SELECT * FROM python_modules where MODULE_NAME =:MODULE_NAME') cursor.execute(None, named_params) pprint(cursor.fetchone()) # ('cx_Oracle', # 'C:\Program ' # 'Files\Python36\lib\site-packages\cx_Oracle.cp36-win_amd64.pyd')
回到顶部
大型的插入操作不需求多次的单独插入,这是因为 Python 通过 cx_Oracle.Cursor.executemany 方法完全支持一次插入多行。
限制执行操作的数量极大地改善了程序性能,因此在编写存在大量插入操作的应用程序时应首先考虑这一功能。
我们首先为 Python 模块列表创建一个表,这次直接从 Python 开始。您将在以后删除该表。
import cx_Oracle # 用于以清晰、可读的形式输出 Python 数据结构 from pprint import pprint from sys import modules # 通过客户端连接oracle connection = cx_Oracle.connect('test/test@testDB') print(connection.version) # 获得游标对象 cursor = connection.cursor () try: # 解析sql语句 cursor.parse("select * dual") # 捕获SQL异常 except cx_Oracle.DatabaseError as e: print(e) # ORA-00923: 未找到要求的 FROM 关键字 # 执行sql 语句 cursor.execute ("select * from dual") # 提取一条数据,返回一个元祖 row = cursor.fetchone() pprint(row) # ('X',) create_table = """ CREATE TABLE python_modules ( module_name VARCHAR2(50) NOT NULL, file_path VARCHAR2(300) NOT NULL ) """ # 执行创建表 create_flag = cursor.execute(create_table) # 添加模块信息 M = [] for m_name, m_info in modules.items(): try: M.append((m_name, m_info.__file__)) except AttributeError: pass print(len(M)) insert_sql = "INSERT INTO python_modules(module_name, file_path) VALUES (:1, :2)" # 在prepare之后,你再去execute的时候,就不用写上sql语句参数了 cursor.prepare(insert_sql) cursor.executemany(None, M) # 注意,第一个参数是None connection.commit() # 提交 # 查询 r = cursor.execute("SELECT COUNT(*) FROM python_modules") pprint(cursor.fetchone()) # 查询列字段信息 column_data_types = cursor.execute('SELECT * FROM python_modules') pprint(column_data_types.description) # [('MODULE_NAME', <class 'cx_Oracle.STRING'>, 50, 50, None, None, 0), # ('FILE_PATH', <class 'cx_Oracle.STRING'>, 300, 300, None, None, 0)] # 取10条记录信息 pprint(len(cursor.fetchmany(10))) # 10 # 取之后所有记录信息,不包括前10条 pprint(len(cursor.fetchall())) # 41 # 绑定变量模式查询 named_params = {'MODULE_NAME': 'cx_Oracle'} cursor.execute('SELECT * FROM python_modules where MODULE_NAME =:MODULE_NAME',named_params) # 在使用已命名的绑定变量时,您可以使用游标的 bindnames() 方法检查目前已指定的绑定变量: print(cursor.bindnames()) pprint(cursor.fetchone()) # ('cx_Oracle', # 'C:\Program ' # 'Files\Python36\lib\site-packages\cx_Oracle.cp36-win_amd64.pyd') # 在绑定时,您可以首先准备该语句,然后利用改变的参数执行 None。 # 根据绑定变量时准备一个语句即足够这一原则, # Oracle 将如同在上例中一样对其进行处理。准备好的语句可执行任意次。 cursor.prepare('SELECT * FROM python_modules where MODULE_NAME =:MODULE_NAME') cursor.execute(None, named_params) pprint(cursor.fetchone()) # ('cx_Oracle', # 'C:\Program ' # 'Files\Python36\lib\site-packages\cx_Oracle.cp36-win_amd64.pyd') # 删除python_modules cursor.execute("DROP TABLE python_modules PURGE") # 关闭游标 cursor.close() # 关闭连接 connection.close () # BLOB & CLOB 格式的创建: # # binary_content = cursor.var(cx_Oracle.BLOB) # binary_content.setvalue(0, content)