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


Posted in Python onApril 09, 2016

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

import os
import sys
from subprocess import Popen, PIPE
 
sql = """
set linesize 400
col owner for a10
col 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 32767
set pagesize 9999
set term off verify off feedback off tab off
set 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 listResult

def 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')

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

Python 相关文章推荐
Python3实现从指定路径查找文件的方法
May 22 Python
python选择排序算法实例总结
Jul 01 Python
Python中http请求方法库汇总
Jan 06 Python
详解python之多进程和进程池(Processing库)
Jun 09 Python
Python基于lxml模块解析html获取页面内所有叶子节点xpath路径功能示例
May 16 Python
Python实现曲线拟合操作示例【基于numpy,scipy,matplotlib库】
Jul 12 Python
django如何连接已存在数据的数据库
Aug 14 Python
python批量修改文件夹及其子文件夹下的文件内容
Mar 15 Python
python 实现矩阵填充0的例子
Nov 29 Python
tensorflow tf.train.batch之数据批量读取方式
Jan 20 Python
pycharm中导入模块错误时提示Try to run this command from the system terminal
Mar 26 Python
python中get和post有什么区别
Jun 19 Python
python调用fortran模块
Apr 08 #Python
python3使用urllib模块制作网络爬虫
Apr 08 #Python
Python抓取电影天堂电影信息的代码
Apr 07 #Python
Python Requests安装与简单运用
Apr 07 #Python
Python Requests 基础入门
Apr 07 #Python
Python检测网站链接是否已存在
Apr 07 #Python
python多进程共享变量
Apr 06 #Python
You might like
PHP 小心urldecode引发的SQL注入漏洞
2011/10/27 PHP
用mysql_fetch_array()获取当前行数据的方法详解
2013/06/05 PHP
实例讲解PHP面向对象之多态
2014/08/20 PHP
Zend Framework实现留言本分页功能(附demo源码下载)
2016/03/22 PHP
php实现学生管理系统
2020/03/21 PHP
php 常用的系统函数
2017/02/07 PHP
PHP迭代器接口Iterator用法分析
2017/12/28 PHP
基于swoole实现多人聊天室
2018/06/14 PHP
js 编写规范
2010/03/03 Javascript
JSONP 跨域访问代理API-yahooapis实现代码
2012/12/02 Javascript
jquery中post方法用法实例
2014/10/21 Javascript
纯JavaScript代码实现移动设备绘图解锁
2015/10/16 Javascript
javascript创建对象的几种模式介绍
2016/05/06 Javascript
React Native实现简单的登录功能(推荐)
2016/09/19 Javascript
JavaScript之RegExp_动力节点Java学院整理
2017/06/29 Javascript
Vue axios 中提交表单数据(含上传文件)
2017/07/06 Javascript
Angularjs的启动过程分析
2017/07/18 Javascript
JS实现十字坐标跟随鼠标效果
2017/12/25 Javascript
Angular实现点击按钮后在上方显示输入内容的方法
2017/12/27 Javascript
详解各版本React路由的跳转的方法
2018/05/10 Javascript
对于防止按钮重复点击的尝试详解
2019/04/22 Javascript
javascript设计模式 ? 命令模式原理与用法实例分析
2020/04/20 Javascript
[14:25]教你分分钟做大人:主宰(HEROS)
2014/12/08 DOTA
基于Python的文件类型和字符串详解
2017/12/21 Python
python如何通过实例方法名字调用方法
2018/03/21 Python
python找出完数的方法
2018/11/12 Python
Django用内置方法实现简单搜索功能的方法
2020/12/18 Python
Orlebar Brown官网:设计师泳裤和泳装
2020/12/08 全球购物
方正Java笔试题
2014/07/03 面试题
日语专业毕业生求职信
2013/12/04 职场文书
副科竞争上岗演讲稿
2014/05/12 职场文书
医院合作协议书
2014/08/19 职场文书
教师作风整改措施思想汇报
2014/10/12 职场文书
银行招聘自荐信
2015/03/06 职场文书
护士工作心得体会
2016/01/25 职场文书
win10双系统怎么删除一个系统?win10电脑有两个系统删除一个的操作方法
2022/07/15 数码科技