这篇文章主要介绍了Python调用SQLPlus来操作和解析Oracle数据库的方法,这样用SQL*Plus方式来分析Oracle中的数据就变得十分方便,需要的朋友可以参考下。
先来看一个简单的利用python调用sqlplus来输出结果的例子:
import osimport sysfrom subprocess import Popen, PIPEsql = """set linesize 400col owner for a10col object_name for a30select owner, object_namefrom dba_objectswhere rownum<=10;"""proc = Popen(["sqlplus", "-S", "/", "as", "sysdba"], stdout=PIPE, stdin=PIPE, stderr=PIPE)proc.stdin.write(sql)(out, err) = proc.communicate()if proc.returncode != 0:print errsys.exit(proc.returncode)else:print out
代码片段:可切换语言,无法单独设置文字格式
用Python查询Oracle,当然最好用cx_Oracle库,但有时候受到种种限制,不能安装Python第三方库,就得利用现有资源,硬着头皮上了。
用Python调用SqlPlus查询Oracle,首先要知道SqlPlus返回结果是什么样的:
(这是空行)Number Name Address------------ ----------- ------------------1001 张三 南京路1002 李四 上海路
代码片段:可切换语言,无法单独设置文字格式
第1行是空行,第2行是字段名称,第3行都是横杠,有空格隔开,第4行开始是查询到的结果。
在查询结果规整的情况下,根据第3行可以很清晰的看到结构,用Python解析起来也比较方便。但是,如果一张表字段特别多,记录数也相当多,那么默认情况下调用SqlPlus查询出的结果会比较乱,这就需要在调用查询之前做一些设定,比如:
printf("hello world!");
代码片段:可切换语言,无法单独设置文字格式
这样的调用查询结果就比较规整了。接下来就是用强大的Python来解析查询结果。
这里封装了一个函数,可以根据传入的SQL语句查询并解析结果,将每行结果存到列表中,列表中的每个元素是一个字段名称与值的映射。
#!/usr/bin/python#coding=UTF-8'''@author: 双子座@开源中国@summary: 通过SqlPlus查询Oracles数据库'''import os;os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.AL32UTF8'gStrConnection = 'username/password@10.123.5.123:1521/ora11g'#解析SqlPlus的查询结果,返回列表def parseQueryResult(listQueryResult):listResult = []#如果少于4行,说明查询结果为空if len(listQueryResult) < 4:return listResult#第0行是空行,第1行可以获取字段名称,第2行可获取SQLPlus原始结果中每列宽度,第3行开始是真正输出# 1 解析第2行,取得每列宽度,放在列表中listStrTmp = listQueryResult[2].split(' ')listIntWidth = []for oneStr in listStrTmp:listIntWidth.append(len(oneStr))# 2 解析第1行,取得字段名称放在列表中listStrFieldName = []iLastIndex = 0lineFieldNames = listQueryResult[1]for iWidth in listIntWidth:#截取[iLastIndex, iLastIndex+iWidth)之间的字符串strFieldName = lineFieldNames[iLastIndex:iLastIndex + iWidth]strFieldName = strFieldName.strip() #去除两端空白符listStrFieldName.append(strFieldName)iLastIndex = iLastIndex + iWidth + 1# 3 第3行开始,解析结果,并建立映射,存储到列表中for i in range(3, len(listQueryResult)):oneLiseResult = unicode(listQueryResult[i], 'UTF-8')fieldMap = {}iLastIndex = 0for j in range(len(listIntWidth)):strFieldValue = oneLiseResult[iLastIndex:iLastIndex + listIntWidth[j]]strFieldValue = strFieldValue.strip()fieldMap[listStrFieldName[j]] = strFieldValueiLastIndex = iLastIndex + listIntWidth[j] + 1listResult.append(fieldMap)return listResultdef QueryBySqlPlus(sqlCommand):global gStrConnection#构造查询命令strCommand = 'sqlplus -S %s <<!\n' % gStrConnectionstrCommand = strCommand + 'set linesize 32767\n'strCommand = strCommand + 'set pagesize 9999\n'strCommand = strCommand + 'set term off verify off feedback off tab off \n'strCommand = strCommand + 'set numwidth 40\n'strCommand = strCommand + sqlCommand + '\n'#调用系统命令收集结果result = os.popen(strCommand)list = []for line in result:list.append(line)return parseQueryResult(list)
代码片段:可切换语言,无法单独设置文字格式
其中os.environ['NLS_LANG']的值来自
select userenv['language'] from dual;
代码片段:可切换语言,无法单独设置文字格式
在调用的时候,只要类似:
listResult = QueryBySqlPlus('select * from studentinfo')
代码片段:可切换语言,无法单独设置文字格式
然后就可以用循环打印出结果了。

更多数据科学知识,请扫码关注:全栈数据

文章转载自全栈数据,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




