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 相关文章推荐
wxPython中listbox用法实例详解
Jun 01 Python
Python实现矩阵加法和乘法的方法分析
Dec 19 Python
django在接受post请求时显示403forbidden实例解析
Jan 25 Python
python 实现语音聊天机器人的示例代码
Dec 02 Python
python中设置超时跳过,超时退出的方式
Dec 13 Python
Python Print实现在输出中插入变量的例子
Dec 25 Python
pytorch构建多模型实例
Jan 15 Python
python next()和iter()函数原理解析
Feb 07 Python
Python pip安装模块提示错误解决方案
May 22 Python
python爬虫中PhantomJS加载页面的实例方法
Nov 12 Python
pandas统计重复值次数的方法实现
Feb 20 Python
Python sklearn分类决策树方法详解
Sep 23 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
解析用PHP读写音频文件信息的详解(支持WMA和MP3)
2013/05/10 PHP
基于PHP文件操作的详解
2013/06/05 PHP
Yii2框架使用计划任务的方法
2016/05/25 PHP
PHP使用两个栈实现队列功能的方法
2018/01/15 PHP
discuz论坛更换域名,详细文件修改步骤
2020/12/09 PHP
JS继承 笔记
2011/07/13 Javascript
javascript中的数字与字符串相加实例分析
2011/08/14 Javascript
详解强大的jQuery选择器之基本选择器、层次选择器
2012/02/07 Javascript
js显示时间 js显示最后修改时间
2013/01/02 Javascript
js实现按钮控制图片360度翻转特效的方法
2015/02/17 Javascript
Javascript将数字转化成为货币格式字符串
2016/06/22 Javascript
Javascript 数组去重的方法(四种)详解及实例代码
2016/11/24 Javascript
Angular中实现树形结构视图实例代码
2017/05/05 Javascript
一步步教你利用Docker设置Node.js
2018/11/20 Javascript
jQuery+css last-child实现选择最后一个子元素操作示例
2018/12/10 jQuery
使用 vue 实例更好的监听事件及vue实例的方法
2019/04/22 Javascript
Layui table field初始化加载时进行隐藏的方法
2019/09/19 Javascript
js键盘事件实现人物的行走
2020/01/17 Javascript
Vue 组件的挂载与父子组件的传值实例
2020/09/02 Javascript
vue中后端做Excel导出功能返回数据流前端的处理操作
2020/09/08 Javascript
swiper4实现移动端导航栏tab滑动切换
2020/10/16 Javascript
[02:02]特效爆炸!DOTA2珍宝之瓶待你开启
2018/08/21 DOTA
python海龟绘图实例教程
2014/07/24 Python
django基础之数据库操作方法(详解)
2017/05/24 Python
利用Python将时间或时间间隔转为ISO 8601格式方法示例
2017/09/05 Python
娇韵诗香港官网:Clarins香港
2020/08/13 全球购物
求∏的近似值,直到最后一项的绝对值小于指定的数
2016/02/12 面试题
报关简历自我评价怎么写
2013/09/19 职场文书
交通安全教育制度
2014/02/02 职场文书
八一慰问活动方案
2014/02/07 职场文书
区域销售主管岗位职责
2014/06/15 职场文书
征兵宣传标语
2014/06/20 职场文书
党员应该树立反腐倡廉的坚定意识思想汇报
2014/09/12 职场文书
求职自我评价范文100字
2014/09/23 职场文书
2015年招生工作总结
2015/05/04 职场文书
离婚答辩状怎么写
2015/05/22 职场文书