Python连接Oracle之环境配置、实例代码及报错解决方法详解


Posted in Python onFebruary 11, 2020

Oracle Client 安装

1、环境

日期:2019年8月1日

公司已经安装好Oracle服务端

Windows版本:Windows10专业版

系统类型:64位操作系统,基于x64的处理器

Python版本:Python 3.6.4 :: Anaconda, Inc.

Python连接Oracle之环境配置、实例代码及报错解决方法详解

2、下载网址

https://www.oracle.com/database/technologies/instant-client/downloads.html

3、解压至目录

Python连接Oracle之环境配置、实例代码及报错解决方法详解

解压后(这里放D盘)

Python连接Oracle之环境配置、实例代码及报错解决方法详解

4、配置环境变量

控制面板\系统和安全\系统 -> 高级系统设置 -> 环境变量

Python连接Oracle之环境配置、实例代码及报错解决方法详解

新建ORACLE_HOME,值为包解压的路径

Python连接Oracle之环境配置、实例代码及报错解决方法详解

编辑PATH,添加%ORACLE_HOME%

Python连接Oracle之环境配置、实例代码及报错解决方法详解

Navicat连接测试

Python连接Oracle之环境配置、实例代码及报错解决方法详解

cx_Oracle

安装命令

conda install cx_Oracle

基础代码

import cx_Oracle
def execute(query):
 db = cx_Oracle.connect('用户名/密码@IP/ServiceName')
 cursor = db.cursor()
 cursor.execute(query)
 result = cursor.fetchall()
 cursor.close()
 db.close()
 return result
def commit(sql):
 db = cx_Oracle.connect('用户名/密码@IP/ServiceName')
 cursor = db.cursor()
 cursor.execute(sql)
 db.commit()
 cursor.close()
 db.close()

封装成类

from cx_Oracle import Connection # conda install cx_Oracle
from conf import CONN, Color
class Oracle(Color):
 def __init__(self, conn=CONN):
  self.db = Connection(*conn, encoding='utf8') # 用户名 密码 IP/ServiceName
  self.cursor = self.db.cursor()
 def __del__(self):
  self.cursor.close()
  self.db.close()
 def commit(self, sql):
  try:
   self.cursor.execute(sql)
   self.db.commit()
  except Exception as e:
   self.red(e)
 def fetchall(self, query):
  self.cursor.execute(query)
  return self.cursor.fetchall()
 def fetchone(self, query, n=9999999):
  self.cursor.execute(query)
  for _ in range(n):
   one = self.cursor.fetchone()
   if one:
    yield one
 def fetchone_dt(self, query, n=9999999):
  self.cursor.execute(query)
  columns = [i[0] for i in self.cursor.description]
  length = len(columns)
  for _ in range(n):
   one = self.cursor.fetchone() # tuple
   yield {columns[i]: one[i] for i in range(length)}
 def read_clob(self, query):
  self.cursor.execute(query)
  one = self.cursor.fetchone()
  while one:
   try:
    yield one[0].read()
   except Exception as e:
    self.red(e)
   one = self.cursor.fetchone()
 def db2sheet(self, query, prefix):
  df = pd.read_sql_query(query, self.db)
  if 'url' in df.columns:
   df['url'] = "'" + df['url']
  df.to_excel(prefix.replace('.xlsx', '')+'.xlsx', index=False)
 def db2sheets(self, queries, prefix):
  writer = pd.ExcelWriter(prefix.replace('.xlsx', '')+'.xlsx')
  for sheet_name, query in queries.items():
   df = pd.read_sql_query(query, self.db)
   if 'url' in df.columns:
    df['url'] = "'" + df['url']
   df.to_excel(writer, sheet_name=sheet_name, index=False)
  writer.save()
 def tb2sheet(self, table):
  sql = "SELECT * FROM " + table
  self.db2sheet(sql, table)
 def insert(self, dt, tb):
  for k, v in dt.items():
   if isinstance(v, str):
    dt[k] = v.replace("'", '').strip()
  ls = [(k, v) for k, v in dt.items() if v is not None]
  sql = 'INSERT INTO %s (' % tb + ','.join(i[0] for i in ls) + \
    ') VALUES (' + ','.join('%r' % i[1] for i in ls) + ')'
  self.commit(sql)
 def insert_clob(self, dt, tb, clob):
  for k, v in dt.items():
   if isinstance(v, str):
    dt[k] = v.replace("'", '').strip()
  # 把超长文本保存在一个变量中
  # declare = "DECLARE variate CLOB := '%s';\n" % dt[clob]
  join = lambda x: '||'.join("'%s'" % x[10922*i: 10922*(i+1)] for i in range(len(x)//10922+1)) # 32768//3
  declare = "DECLARE variate CLOB := %s;\n" % join(dt[clob])
  dt[clob] = 'variate'
  ls = [(k, v) for k, v in dt.items() if v is not None]
  sql = 'INSERT INTO %s (' % tb + ','.join(i[0] for i in ls) + ') VALUES (' +\
    ','.join('%r' % i[1] for i in ls) + ');'
  sql = declare + 'BEGIN\n%s\nEND;' % sql.replace("'variate'", 'variate')
  self.commit(sql)
 def update(self, dt_update, dt_condition, table):
  sql = 'UPDATE %s SET ' % table + ','.join('%s=%r' % (k, v) for k, v in dt_update.items()) \
    + ' WHERE ' + ' AND '.join('%s=%r' % (k, v) for k, v in dt_condition.items())
  self.commit(sql)
 def truncate(self, tb):
  self.commit('truncate table ' + tb)
db_read = Oracle()
fetchall = db_read.fetchall
fetchone = db_read.fetchone
read_clob = db_read.read_clob
if __name__ == '__main__':
 query = '''
 '''.strip()
 for i in fetchone(query, 99):
  print(i)

conf

CONN = ('用户名', '密码', 'IP/ServiceName')
conn = '用户名/密码@IP/ServiceName'

文本字符串查询

class INSTR(Oracle):
 """文本字符串查询"""
 def highlight_instr(self, table, field, keyword, clob=True):
  sql = "SELECT %s FROM %s WHERE INSTR(%s,'%s')>0" % (field, table, field, keyword)
  if clob:
   for i in self.read_clob(sql):
    self.highlight(i, keyword)
  else:
   for i, in self.fetchone(sql):
    self.highlight(i, keyword)
 def regexp_instr(self, table, field, pattern, regexp=True, clob=True):
  sql = "SELECT %s FROM %s WHERE INSTR(%s,'%s')>0" % (field, table, field, pattern)
  sql = sql.replace('INSTR', 'REGEXP_INSTR') if regexp else sql
  if clob:
   for i in self.read_clob(sql):
    yield i
  else:
   for i, in self.fetchone(sql):
    yield i

一个简单的建表示例

-- 建表
CREATE TABLE table_name
(
serial_number  NUMBER(10),
collect_date  DATE,
url    VARCHAR2(255),
long_text   CLOB,
price    NUMBER(10)-- 若需要精确到小数点2位,按分存储,/100还原到元
);
-- 给表添加备注
COMMENT ON TABLE table_name IS '中文表名';
-- 给表字段添加备注
COMMENT ON COLUMN table_name.serial_number IS '编号';
COMMENT ON COLUMN table_name.collect_date IS '日期';
COMMENT ON COLUMN table_name.url IS 'URL';
COMMENT ON COLUMN table_name.long_text IS '长文本';
COMMENT ON COLUMN table_name.price IS '价钱';
-- 插入
INSERT INTO table_name(collect_date) VALUES (DATE'2019-08-23');
INSERT INTO table_name(long_text) VALUES ('a');
INSERT INTO table_name(long_text) VALUES ('b');
-- 查询
SELECT * FROM table_name WHERE TO_CHAR(long_text) in ('a','b');
-- 查建表语句(表名大写)
SELECT dbms_metadata.get_ddl('TABLE','TABLE_NAME') FROM dual;
-- 删表
DROP TABLE table_name;

sqlalchemy

import os # 解决【UnicodeEncodeError: 'ascii' codec can't encode character】问题
os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.AL32UTF8'
# os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
from cx_Oracle import makedsn
from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# 连接数据库(ORA-12505: TNS:listener does not currently know of SID given in connect descriptor)
ip = ''
port = ''
tnsname = '' # 实例名
uname = '' # 用户名
pwd = '' # 密码
dsnStr = makedsn(ip, port, service_name=tnsname)
connect_str = "oracle://%s:%s@%s" % (uname, pwd, dsnStr)
# 创建连接引擎,这个engine是lazy模式,直到第一次被使用才真实创建
engine = create_engine(connect_str, encoding='utf-8')
# 创建对象的基类
Base = declarative_base()
class Student(Base):
 # 表名
 __tablename__ = 'student'
 # 表字段
 sid = Column(String(20), primary_key=True)
 age = Column(Integer)
# 建表(继承Base的所有表)
Base.metadata.create_all(bind=engine)
# 使用ORM操作数据库
Session = sessionmaker(bind=engine) # 创建ORM基类
session = Session() # 创建ORM对象
tb_obj = Student(sid='a6', age=18) # 创建表对象
session.add(tb_obj) # 添加到ORM对象(插入数据)
session.commit() # 提交
session.close() # 关闭ORM对象
# 删表(继承Base的所有表)
Base.metadata.drop_all(engine)

报错处理

DPI-1047: 64-bit Oracle Client library cannot be loaded

首先操作系统位数、python位数、cx_Oracle版本要对应上;另外可能缺【Visual C++】

每次装完后,要重启pycharm和python

ORA-12170: TNS:Connect timeout occurred

打开终端ping一下

检查【主机名或IP地址】、【服务名或SID】、【用户名】和【密码】是否填对

中文乱码

encoding=‘utf8'

ORA-00972: identifier is too long

insert语句中出现'之类的字符

解决方法:将可能报错的字符替换掉

ORA-64203: Destination buffer too small to hold CLOB data after character set conversion.

select TO_CHAR(long_text) from table_name,目标缓冲区太小,无法储存CLOB转换字符后的数据

解决方法:不在SQL用TO_CHAR,改在Python中用read(如上代码所示)

ORA-01704: string literal too long

虽然CLOB可以保存长文本,但是SQL语句有长度限制

解决方法:把超长文本保存在一个变量中(如上代码所示)

PLS-00172: string literal too long

字符串长度>32767(215-1)

解决方法:使用'||'来连接字符串(如上代码所示)

ORA-00928: missing SELECT keyword

INSERT操作时,表字段命名与数据库内置名称冲突,如:ID、LEVEL、DATE等

解决方法:建立命名规范

cx_Oracle.DatabaseError: ORA-12505: TNS:listener does not currently know of SID given in connect descriptor

使用sqlalchemy时的报错

原因可能是目标数据库是集群部署的,可以咨询一下DBA,或见上面代码from cx_Oracle import makedsn

UnicodeEncodeError: 'ascii' codec can't encode character

使用sqlalchemy时的报错,插入中文字符引起

解决方法是设置os.environ['NLS_LANG']

更多关于Python连接Oracle之环境配置、实例代码及报错解决方法请查看下面的相关链接

Python 相关文章推荐
python递归计算N!的方法
May 05 Python
在Django框架中伪造捕捉到的URLconf值的方法
Jul 18 Python
使用Python的Twisted框架构建非阻塞下载程序的实例教程
May 25 Python
Python实现命令行通讯录实例教程
Aug 18 Python
Python实现登录接口的示例代码
Jul 21 Python
Python Dataframe 指定多列去重、求差集的方法
Jul 10 Python
Python函数中不定长参数的写法
Feb 13 Python
Python3基础教程之递归函数简单示例
Jun 07 Python
python django下载大的csv文件实现方法分析
Jul 19 Python
对Django的restful用法详解(自带的增删改查)
Aug 28 Python
解决pyPdf和pyPdf2在合并pdf时出现异常的问题
Apr 03 Python
Python3.9.0 a1安装pygame出错解决全过程(小结)
Feb 02 Python
利用python中集合的唯一性实现去重
Feb 11 #Python
TensorFLow 变量命名空间实例
Feb 11 #Python
TensorFlow 输出checkpoint 中的变量名与变量值方式
Feb 11 #Python
Python中文分词库jieba,pkusegwg性能准确度比较
Feb 11 #Python
pytorch中图像的数据格式实例
Feb 11 #Python
对tensorflow中tf.nn.conv1d和layers.conv1d的区别详解
Feb 11 #Python
python中文分词库jieba使用方法详解
Feb 11 #Python
You might like
DC四月将推出百页特刊漫画 纪念小丑诞生80周年
2020/04/09 欧美动漫
espresso double下 咖啡粉超细时 饼压力对咖啡的影响
2021/03/03 冲泡冲煮
thinkPHP5.0框架API优化后的友好性分析
2017/03/17 PHP
SyntaxHighlighter代码加色使用方法
2008/09/07 Javascript
C#中TrimStart,TrimEnd,Trim在javascript上的实现
2011/01/17 Javascript
JsDom 编程小结
2011/08/09 Javascript
js保留小数点后几位的写法
2014/01/03 Javascript
使用js操作css实现js改变背景图片示例
2014/03/10 Javascript
jquery实现带二级菜单的导航示例
2014/04/28 Javascript
基于javascript实现单选及多选的向右和向左移动实例
2015/07/25 Javascript
jquery基本选择器匹配多个元素的实现方法
2016/09/05 Javascript
JS实用的带停顿的逐行文本循环滚动效果实例
2016/11/23 Javascript
微信小程序 switch组件详解及简单实例
2017/01/10 Javascript
js实现简单的手风琴效果
2017/02/27 Javascript
ReactNative之FlatList的具体使用方法
2017/11/29 Javascript
AngularJS实现的生成随机数与猜数字大小功能示例
2017/12/25 Javascript
Angular6封装http请求的步骤详解
2018/08/13 Javascript
node中的密码安全(加密)
2018/09/17 Javascript
JS实现选项卡效果的代码实例
2019/05/20 Javascript
JS检测浏览器开发者工具是否打开的方法详解
2020/10/02 Javascript
TensorFlow用expand_dim()来增加维度的方法
2018/07/26 Python
使用pytorch进行图像的顺序读取方法
2018/07/27 Python
python检测文件夹变化,并拷贝有更新的文件到对应目录的方法
2018/10/17 Python
树莓派4B+opencv4+python 打开摄像头的实现方法
2019/10/18 Python
PyTorch的自适应池化Adaptive Pooling实例
2020/01/03 Python
Anaconda使用IDLE的实现示例
2020/09/23 Python
H5最强接口之canvas实现动态图形功能
2019/05/31 HTML / CSS
Foot Locker澳洲官网:美国运动服和鞋类零售商
2019/10/11 全球购物
网络教育毕业生自我鉴定
2013/10/10 职场文书
满月酒主持词
2014/03/27 职场文书
2014年国庆节演讲稿
2014/09/02 职场文书
2014年设计师工作总结
2014/11/25 职场文书
营销计划书
2015/01/17 职场文书
敬业奉献模范事迹材料(2016精选版)
2016/02/26 职场文书
深入浅析Django MTV模式
2021/09/04 Python
redis数据一致性的实现示例
2022/03/18 Redis