首页 > 编程 > Python > 正文

Python调用SQLPlus来操作和解析Oracle数据库的方法

2020-01-04 17:33:38
字体:
来源:转载
供稿:网友
这篇文章主要介绍了Python调用SQLPlus来操作和解析Oracle数据库的方法,这样用SQL*Plus方式来分析Oracle中的数据就变得十分方便,需要的朋友可以参考下
 

先来看一个简单的利用python调用sqlplus来输出结果的例子:

import osimport sysfrom subprocess import Popen, PIPE sql = """set linesize 400col owner for a10col object_name for a30 select owner, object_name from dba_objects where 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 err  sys.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查询出的结果会比较乱,这就需要在调用查询之前做一些设定,比如:

set linesize 32767set pagesize 9999set term off verify off feedback off tab offset numwidth 40

这样的调用查询结果就比较规整了。接下来就是用强大的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 = 0  lineFieldNames = 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 = 0    for j in range(len(listIntWidth)):      strFieldValue = oneLiseResult[iLastIndex:iLastIndex + listIntWidth[j]]      strFieldValue = strFieldValue.strip()      fieldMap[listStrFieldName[j]] = strFieldValue      iLastIndex = iLastIndex + listIntWidth[j] + 1    listResult.append(fieldMap)  return listResultdef QueryBySqlPlus(sqlCommand):  global gStrConnection  #构造查询命令  strCommand = 'sqlplus -S %s <<!/n' % gStrConnection  strCommand = 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')

然后就可以用循环打印出结果了。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表