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列表操作使用示例分享
Feb 21 Python
Python实例分享:快速查找出被挂马的文件
Jun 08 Python
Python中subprocess模块用法实例详解
May 20 Python
使用Python下载歌词并嵌入歌曲文件中的实现代码
Nov 13 Python
Python复制Word内容并使用格式设字体与大小实例代码
Jan 22 Python
对python字典元素的添加与修改方法详解
Jul 06 Python
pycharm远程linux开发和调试代码的方法
Jul 17 Python
Python常见数据结构之栈与队列用法示例
Jan 14 Python
python添加菜单图文讲解
Jun 04 Python
Python3常见函数range()用法详解
Dec 30 Python
python3爬虫GIL修改多线程实例讲解
Nov 24 Python
python中tkinter复选框使用操作
Nov 11 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数据缓存的使用说明
2013/05/10 PHP
PHP实现的交通银行网银在线支付接口ECSHOP插件和使用例子
2014/05/10 PHP
常用PHP封装分页工具类
2017/01/14 PHP
php下载远程大文件(获取远程文件大小)的实例
2017/06/17 PHP
实例讲解通过​PHP创建数据库
2019/01/20 PHP
PHP常用的类封装小结【4个工具类】
2019/06/28 PHP
laravel Task Scheduling(任务调度)在windows下的使用详解
2019/10/22 PHP
基于jQuery的日期选择控件
2009/10/27 Javascript
潜说js对象和数组
2011/05/25 Javascript
js函数名与form表单元素同名冲突的问题
2014/03/07 Javascript
AngularJs篇:使用AngularJs打造一个简易权限系统的实现代码
2016/12/26 Javascript
Vue 过渡(动画)transition组件案例详解
2017/01/22 Javascript
原生JS实现跑马灯效果
2017/02/20 Javascript
Three.js获取鼠标点击的三维坐标示例代码
2017/03/24 Javascript
angular2+nodejs实现图片上传功能
2017/03/27 NodeJs
vue.js实例对象+组件树的详细介绍
2017/10/20 Javascript
使用webpack搭建react开发环境的方法
2018/05/15 Javascript
JS实现的点击按钮图片上下滚动效果示例
2019/01/28 Javascript
微信小程序wx.request拦截器使用详解
2019/07/09 Javascript
vue实现下拉加载其实没那么复杂
2019/08/13 Javascript
js设计模式之代理模式及订阅发布模式实例详解
2019/08/15 Javascript
Vue中的this.$options.data()和this.$data用法说明
2020/07/26 Javascript
[01:32]DOTA2 2015国际邀请赛中国区预选赛第四日战报
2015/05/29 DOTA
Numpy array数据的增、删、改、查实例
2018/06/04 Python
python3解析库pyquery的深入讲解
2018/06/26 Python
python散点图实例之随机漫步
2018/08/27 Python
CSS3模块的目前的状况分析
2010/02/24 HTML / CSS
美国沃尔玛网上超市:Walmart
2020/08/14 全球购物
学校安全工作制度
2014/01/19 职场文书
高中学生会竞选演讲稿
2014/08/25 职场文书
机关班子查摆问题及整改措施
2014/10/28 职场文书
专职安全员岗位职责
2015/04/11 职场文书
结婚喜宴祝酒词
2015/08/10 职场文书
2019年入党思想汇报
2019/03/25 职场文书
2019年教师节活动策划方案
2019/09/09 职场文书
python批量创建变量并赋值操作
2021/06/03 Python