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中字符串类型json操作的注意事项
May 02 Python
Python 使用类写装饰器的小技巧
Sep 30 Python
解决Python获取字典dict中不存在的值时出错问题
Oct 17 Python
从运行效率与开发效率比较Python和C++
Dec 14 Python
python 定时任务去检测服务器端口是否通的实例
Jan 26 Python
python 返回一个列表中第二大的数方法
Jul 09 Python
Tensorflow实现部分参数梯度更新操作
Jan 23 Python
python程序输出无内容的解决方式
Apr 09 Python
详解python中groupby函数通俗易懂
May 14 Python
利用python3筛选excel中特定的行(行值满足某个条件/行值属于某个集合)
Sep 04 Python
python实现图片九宫格分割的示例
Apr 25 Python
Python快速优雅的批量修改Word文档样式
May 20 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
德生PL990,目前市面上唯一一款便携式插卡蓝牙全波段高性能收音机
2021/03/02 无线电
通俗易懂的php防注入代码
2010/04/07 PHP
微信扫描二维码登录网站代码示例
2013/12/30 PHP
必须收藏的23个php实用代码片段
2016/02/02 PHP
ThinkPHP3.2.1图片验证码实现方法
2016/08/19 PHP
PHP 文件上传后端处理实用技巧方法
2017/01/06 PHP
PHP命令Command模式用法实例分析
2018/08/08 PHP
共享自己写一个框架DreamScript
2007/01/20 Javascript
ajax更新数据后,jquery、jq失效问题
2011/03/16 Javascript
ie6下png图片背景不透明的解决办法使用js实现
2013/01/11 Javascript
laytpl 精致巧妙的JavaScript模板引擎
2014/08/29 Javascript
jQuery实现动态表单验证时文本框抖动效果完整实例
2015/08/21 Javascript
简述Matlab中size()函数的用法
2016/03/20 Javascript
JavaScript 数组- Array的方法总结(推荐)
2016/07/21 Javascript
vue中 this.$set的用法详解
2019/09/06 Javascript
Javascript Symbol原理及使用方法解析
2020/10/22 Javascript
简单理解Python中基于生成器的状态机
2015/04/13 Python
Python编程实现输入某年某月某日计算出这一天是该年第几天的方法
2017/04/18 Python
Python使用微信SDK实现的微信支付功能示例
2017/06/30 Python
Python开发中爬虫使用代理proxy抓取网页的方法示例
2017/09/26 Python
详解使用 pyenv 管理多个版本 python 环境
2017/10/19 Python
python爬虫之自动登录与验证码识别
2020/06/15 Python
Python求一批字符串的最长公共前缀算法示例
2019/03/02 Python
在Tensorflow中实现leakyRelu操作详解(高效)
2020/06/30 Python
关于python中导入文件到list的问题
2020/10/31 Python
利用HTML5绘制点线面组成的3D图形的示例
2015/05/12 HTML / CSS
意大利奢侈品网站:Italist
2016/08/23 全球购物
白色公司:The White Company
2017/10/11 全球购物
教育技术学专业职业规划书
2014/03/03 职场文书
现场活动策划方案
2014/08/22 职场文书
写给医院的感谢信
2015/01/22 职场文书
团队拓展训练心得体会
2016/01/12 职场文书
Python实现学生管理系统(面向对象版)
2021/06/24 Python
gateway网关接口请求的校验方式
2021/07/15 Java/Android
SpringCloud项目如何解决log4j2漏洞
2022/04/10 Java/Android
Java实现HTML转为Word的示例代码
2022/06/28 Java/Android