Python连接Oracle之环境配置、实例代码及报错解决方法详解
OracleClient安装
1、环境
日期:2019年8月1日
公司已经安装好Oracle服务端
Windows版本:Windows10专业版
系统类型:64位操作系统,基于x64的处理器
Python版本:Python3.6.4::Anaconda,Inc.
2、下载网址
https://www.oracle.com/database/technologies/instant-client/downloads.html
3、解压至目录
解压后(这里放D盘)
4、配置环境变量
控制面板\系统和安全\系统->高级系统设置->环境变量
新建ORACLE_HOME,值为包解压的路径
编辑PATH,添加%ORACLE_HOME%
Navicat连接测试
cx_Oracle
安装命令
condainstallcx_Oracle
基础代码
importcx_Oracle defexecute(query): db=cx_Oracle.connect('用户名/密码@IP/ServiceName') cursor=db.cursor() cursor.execute(query) result=cursor.fetchall() cursor.close() db.close() returnresult defcommit(sql): db=cx_Oracle.connect('用户名/密码@IP/ServiceName') cursor=db.cursor() cursor.execute(sql) db.commit() cursor.close() db.close()
封装成类
fromcx_OracleimportConnection#condainstallcx_Oracle fromconfimportCONN,Color classOracle(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() defcommit(self,sql): try: self.cursor.execute(sql) self.db.commit() exceptExceptionase: self.red(e) deffetchall(self,query): self.cursor.execute(query) returnself.cursor.fetchall() deffetchone(self,query,n=9999999): self.cursor.execute(query) for_inrange(n): one=self.cursor.fetchone() ifone: yieldone deffetchone_dt(self,query,n=9999999): self.cursor.execute(query) columns=[i[0]foriinself.cursor.description] length=len(columns) for_inrange(n): one=self.cursor.fetchone()#tuple yield{columns[i]:one[i]foriinrange(length)} defread_clob(self,query): self.cursor.execute(query) one=self.cursor.fetchone() whileone: try: yieldone[0].read() exceptExceptionase: self.red(e) one=self.cursor.fetchone() defdb2sheet(self,query,prefix): df=pd.read_sql_query(query,self.db) if'url'indf.columns: df['url']="'"+df['url'] df.to_excel(prefix.replace('.xlsx','')+'.xlsx',index=False) defdb2sheets(self,queries,prefix): writer=pd.ExcelWriter(prefix.replace('.xlsx','')+'.xlsx') forsheet_name,queryinqueries.items(): df=pd.read_sql_query(query,self.db) if'url'indf.columns: df['url']="'"+df['url'] df.to_excel(writer,sheet_name=sheet_name,index=False) writer.save() deftb2sheet(self,table): sql="SELECT*FROM"+table self.db2sheet(sql,table) definsert(self,dt,tb): fork,vindt.items(): ifisinstance(v,str): dt[k]=v.replace("'",'').strip() ls=[(k,v)fork,vindt.items()ifvisnotNone] sql='INSERTINTO%s('%tb+','.join(i[0]foriinls)+\ ')VALUES('+','.join('%r'%i[1]foriinls)+')' self.commit(sql) definsert_clob(self,dt,tb,clob): fork,vindt.items(): ifisinstance(v,str): dt[k]=v.replace("'",'').strip() #把超长文本保存在一个变量中 #declare="DECLAREvariateCLOB:='%s';\n"%dt[clob] join=lambdax:'||'.join("'%s'"%x[10922*i:10922*(i+1)]foriinrange(len(x)//10922+1))#32768//3 declare="DECLAREvariateCLOB:=%s;\n"%join(dt[clob]) dt[clob]='variate' ls=[(k,v)fork,vindt.items()ifvisnotNone] sql='INSERTINTO%s('%tb+','.join(i[0]foriinls)+')VALUES('+\ ','.join('%r'%i[1]foriinls)+');' sql=declare+'BEGIN\n%s\nEND;'%sql.replace("'variate'",'variate') self.commit(sql) defupdate(self,dt_update,dt_condition,table): sql='UPDATE%sSET'%table+','.join('%s=%r'%(k,v)fork,vindt_update.items())\ +'WHERE'+'AND'.join('%s=%r'%(k,v)fork,vindt_condition.items()) self.commit(sql) deftruncate(self,tb): self.commit('truncatetable'+tb) db_read=Oracle() fetchall=db_read.fetchall fetchone=db_read.fetchone read_clob=db_read.read_clob if__name__=='__main__': query=''' '''.strip() foriinfetchone(query,99): print(i)
conf
CONN=('用户名','密码','IP/ServiceName') conn='用户名/密码@IP/ServiceName'
文本字符串查询
classINSTR(Oracle): """文本字符串查询""" defhighlight_instr(self,table,field,keyword,clob=True): sql="SELECT%sFROM%sWHEREINSTR(%s,'%s')>0"%(field,table,field,keyword) ifclob: foriinself.read_clob(sql): self.highlight(i,keyword) else: fori,inself.fetchone(sql): self.highlight(i,keyword) defregexp_instr(self,table,field,pattern,regexp=True,clob=True): sql="SELECT%sFROM%sWHEREINSTR(%s,'%s')>0"%(field,table,field,pattern) sql=sql.replace('INSTR','REGEXP_INSTR')ifregexpelsesql ifclob: foriinself.read_clob(sql): yieldi else: fori,inself.fetchone(sql): yieldi
一个简单的建表示例
--建表 CREATETABLEtable_name ( serial_numberNUMBER(10), collect_dateDATE, urlVARCHAR2(255), long_textCLOB, priceNUMBER(10)--若需要精确到小数点2位,按分存储,/100还原到元 ); --给表添加备注 COMMENTONTABLEtable_nameIS'中文表名'; --给表字段添加备注 COMMENTONCOLUMNtable_name.serial_numberIS'编号'; COMMENTONCOLUMNtable_name.collect_dateIS'日期'; COMMENTONCOLUMNtable_name.urlIS'URL'; COMMENTONCOLUMNtable_name.long_textIS'长文本'; COMMENTONCOLUMNtable_name.priceIS'价钱'; --插入 INSERTINTOtable_name(collect_date)VALUES(DATE'2019-08-23'); INSERTINTOtable_name(long_text)VALUES('a'); INSERTINTOtable_name(long_text)VALUES('b'); --查询 SELECT*FROMtable_nameWHERETO_CHAR(long_text)in('a','b'); --查建表语句(表名大写) SELECTdbms_metadata.get_ddl('TABLE','TABLE_NAME')FROMdual; --删表 DROPTABLEtable_name;
sqlalchemy
importos#解决【UnicodeEncodeError:'ascii'codeccan'tencodecharacter】问题 os.environ['NLS_LANG']='AMERICAN_AMERICA.AL32UTF8' #os.environ['NLS_LANG']='SIMPLIFIEDCHINESE_CHINA.UTF8' fromcx_Oracleimportmakedsn fromsqlalchemyimportcreate_engine,Column,String,Integer fromsqlalchemy.ext.declarativeimportdeclarative_base fromsqlalchemy.ormimportsessionmaker #连接数据库(ORA-12505:TNS:listenerdoesnotcurrentlyknowofSIDgiveninconnectdescriptor) 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() classStudent(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-bitOracleClientlibrarycannotbeloaded
首先操作系统位数、python位数、cx_Oracle版本要对应上;另外可能缺【VisualC++】
每次装完后,要重启pycharm和python
ORA-12170:TNS:Connecttimeoutoccurred
打开终端ping一下
检查【主机名或IP地址】、【服务名或SID】、【用户名】和【密码】是否填对
中文乱码
encoding=‘utf8'
ORA-00972:identifieristoolong
insert语句中出现'之类的字符
解决方法:将可能报错的字符替换掉
ORA-64203:DestinationbuffertoosmalltoholdCLOBdataaftercharactersetconversion.
selectTO_CHAR(long_text)fromtable_name,目标缓冲区太小,无法储存CLOB转换字符后的数据
解决方法:不在SQL用TO_CHAR,改在Python中用read(如上代码所示)
ORA-01704:stringliteraltoolong
虽然CLOB可以保存长文本,但是SQL语句有长度限制
解决方法:把超长文本保存在一个变量中(如上代码所示)
PLS-00172:stringliteraltoolong
字符串长度>32767(215-1)
解决方法:使用'||'来连接字符串(如上代码所示)
ORA-00928:missingSELECTkeyword
INSERT操作时,表字段命名与数据库内置名称冲突,如:ID、LEVEL、DATE等
解决方法:建立命名规范
cx_Oracle.DatabaseError:ORA-12505:TNS:listenerdoesnotcurrentlyknowofSIDgiveninconnectdescriptor
使用sqlalchemy时的报错
原因可能是目标数据库是集群部署的,可以咨询一下DBA,或见上面代码fromcx_Oracleimportmakedsn
UnicodeEncodeError:'ascii'codeccan'tencodecharacter
使用sqlalchemy时的报错,插入中文字符引起
解决方法是设置os.environ['NLS_LANG']
更多关于Python连接Oracle之环境配置、实例代码及报错解决方法请查看下面的相关链接
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。