尝试在 Python 2.7 中将 SQL*Plus 输出分配给元组(二维数组)

Posted

技术标签:

【中文标题】尝试在 Python 2.7 中将 SQL*Plus 输出分配给元组(二维数组)【英文标题】:Trying To Assign SQL*Plus Output To Tupple (Two-Dimensional Array) In Python 2.7 【发布时间】:2021-08-09 12:20:07 【问题描述】:

在工作中,由于安全环境的原因,我们无法使用 cx_oracle 模块。我们被困在使用 SQLPLUS 中。查找在线代码,我能够成功运行 SQL 查询,但问题是查询的结果不容易处理。我想知道是否有人可以帮助修复输出,以便它将查询结果放入一个元组中,其中二维表示列和行。这是我到目前为止的代码:

    from subprocess import Popen, PIPE
 
#function that takes the sqlCommand and connectString and returns the queryReslut and errorMessage (if any)
def runSqlQuery(sqlCommand, connectString):
   session = Popen(['sqlplus', '-S', connectString], stdin=PIPE, stdout=PIPE, stderr=PIPE)
   session.stdin.write(sqlCommand)
   return session.communicate()

函数调用如下:

sqlCommand='select * from <database-name-removed> where payrollnumber in (1111);'
connectString=username + '/' + password + '@SERVER'
queryResult, errorMessage = runSqlQuery(sqlCommand, connectString)

当我执行“打印查询结果”时,我会收到一种奇怪格式的输出,如下所示:

  PERSONID PAYROLLNUMBER EMPLOYEEPREFIX LASTNAME
---------- ------------- -------------- ------------------------------
FIRSTNAME                 MI       ACTIVE      UN_ID
------------------------- ---- ---------- ----------
     11111         99999                NEWMAN
ALFRED                             1

这显然不容易解析。我想保留第 0 行的列名。在这个例子中,元组看起来像这样:

tupple=["PERSONID", "PAYROLLNUMBER", "EMPLOYEEPREFIX", "LASTNAME", "FIRSTNAME", "MI", "ACTIVE", "UN_ID"]
       ["11111", "99999", "", "NEWMAN", "ALFRED", "", "1", ""]

在第二行数据中,MI、EMPLOYEEPREFIX 和 UN_ID 为空白,这就是缺失值的原因。

谢谢!

【问题讨论】:

这对于安全性而言更糟糕,因为它会阻止您使用绑定参数,因此会增加 SQL 注入攻击的风险(以及引入由错误触发的潜在漏洞)解析结果的代码)。与您的安全人员谈谈,他们应该例外。 (另外,除非在其间的十年中对其进行了大幅重新设计,否则 sqlplus 在安全、明确的使用方面的设计特别糟糕;在以前的工作中,我使用 cx_Oracle 构建了一个 Python 工具来准确地替换它原因) 很遗憾,我不是系统管理员,所以无法在服务器上安装软件。系统管理员是外包的,所以我们必须提交请求,但这些请求通常会被拒绝。如果有人真的有解决方案,这将是最好的。我肯定更喜欢使用 cx_Oracle。 在此处提出系统管理员同意批准的请求应该很容易;安全性和性能优势是非常重要的。也就是说,在大多数情况下,您不需要 需要 root 访问权限来安装 Python 模块 - 如果磁盘上有任何位置 可以 写入,则可以将它们安装在那里(或在那里的 virtualenv 中)并将它们添加到 sys.path 如果您真的不能使用 Oracle 的 cx_Oracle 模块,请使用大的 SET LINESIZE 运行 SQL*Plus。使用 SET NULL 为空值打印一些内容。或者查看blogs.oracle.com/opal/… 并获取可以使用标准 Python csv 模块解析的 CSV。 【参考方案1】:

连接列并在它们之间放置分隔符。例如,这是我在 Python 中使用 sqlplus 获取当前 SCN 号的方法:

    scn_query = """
COLUMN SCN FORMAT 999999999999999
CREATE TABLE tempscnnumber ( scn varchar2(25));
INSERT INTO tempscnnumber VALUES(
TO_CHAR(userenv('commitscn'),999999999999999));
commit;
select 'S'||'CN:'||to_number(SCN) from tempscnnumber;
drop table tempscnnumber;
exit;
    """

稍后在代码中,我在 sqlplus 的输出中搜索 SCN:

    """
Output is like:

'S'||'CN:'||CURRENT_SCN
--------------------------------------------
SCN:77262587

    """

# Find the line with SCN
    for line in output:
        if line[0:4]=="SCN:":
            scn = line[4:]
            return int(scn)

    return -1

不漂亮。如果你想要一堆列,只需将它们与 ||':'|| 连接起来如果您的输出没有冒号或使用 ||'%*%%^&'||或任何不在您的输出中的字符串。

鲍比

【讨论】:

如果原始发帖人只能在 SQL*Plus 中运行查询,我仍然会投票使用 SQL*Plus 的 SET MARKUP CSV 模式,而不是手动连接。当然,如果查询是在 Python cx_Oracle 中运行的,则不需要这些!

以上是关于尝试在 Python 2.7 中将 SQL*Plus 输出分配给元组(二维数组)的主要内容,如果未能解决你的问题,请参考以下文章

在 python 2.7 中将包含 datetime.timedelta 的 numpy 数组转换为秒的优雅方法

在Python中将sql查询存储为单个变量[重复]

在python中将html图形元素转换为sql

sql 谁更新了plu

使用blob在python中将pdf上传到sql-alchemy

有效地将字符串转换为 python 2.7 的 unicode