我的目标是使用Win32com模块通过Python控制台显示SQL查询。我可以使用comobject访问并成功显示SQL查询的字段,但当我尝试显示行时,我会陷入异常。
背景
我使用过PYODBC,它工作得很好,但根据安装了什么SQL提供程序以及是否强制执行TLS 1.2存在限制。软件有时安装在外部SQL服务器上,因此软件服务器上没有能够始终建立连接的提供商。这就是为什么我现在通过com对象使用软件的内核来访问DB,因为这避免了提供商需要安装或最新的Windows更新以允许TLS 1.2连接等的陷阱。
使用Fields 为我工作的Win32com代码
import win32com.client
import win32com
"""Connection"""
objprox = win32com.client.Dispatch("****.DbObjectProxy") #Blanked out for security of Software
"""Set Query"""
sql1 = "select * from ServiceConsumer_t"
dbq1 = objprox.DoDatabaseQuery(sql1)
dbq1.Open(sql1)
"""Specify & Print result"""
while not dbq1.EOF:
col1 = dbq1.Fields("ID").Value
dbq1.MoveNext()
print(col1)
"""Close Session"""
dbq1.Close()
以上输出为:
{9CAFD41E-D322-4234-BF80-CF6E11A724A0}
{CE4AAE72-0889-41E8-BDB2-ED96696DDB91}
{DC18008F-2C84-4EB4-BCCB-D94FF96E0564}
{1AAB143C-8393-4C1E-BE94-7AB44788D4E4}
这是正确的,因为我正在指定要输出的ID列,并使用MoveNext()
进行迭代。这表明我已经接近了我的目标,然而,下面显示行的代码似乎从未奏效,我现在不明白为什么了?
Win32com无法显示行的代码:
import win32com.client
import win32com
"""Connection"""
objprox = win32com.client.Dispatch("*****.DbObjectProxy") #Blanked out for security of Software
"""Set Query"""
sql2 = "select * from ServiceConsumer_t"
dbq2 = objprox.DoDatabaseQuery(sql2)
dbq2.Open(sql2)
"""Specify & Print result"""
while not dbq2.EOF:
dbq2.MoveFirst()
res = dbq2.GetRows()
dbq2.MoveNext()
print(res)
"""Close Session"""
dbq2.Close()
由此,我只得到对象GetRows
没有属性的异常。从网上看,围绕这一点的内容很少。你能建议一下为什么代码不能显示所有行的结果吗?理想情况下,我希望列名称也显示出来。
假设COM对象与ADODB对象对齐,则GetRows
执行以下操作:
将Recordset对象的多条记录检索到数组中。
在Python中,此数组或多维对象转换为嵌套元组,没有类似列名的元数据:
rst.MoveFirst()
res = rst.GetRows() # TUPLE OF TUPLES
# LOOP THROUGH ROWS
for i in range(len(res)):
# LOOP THROUGH COLUMNS
for j in range(len(res[i])):
print(res[i][j])
ADODB示例:
import win32com.client
# OPEN SQL SERVER DATABASE CONNECTION
conn = win32com.client.gencache.EnsureDispatch("ADODB.Connection")
conn.Open(
"Driver={ODBC Driver 17 for SQL Server};"
f"Server=myServer;Database=myDatabase;"
"Trusted_Connection=Yes;"
)
# OPEN RECORDSET
rst = win32com.client.gencache.EnsureDispatch("ADODB.Recordset")
rst.Open("SELECT * FROM myTable", conn)
rst.MoveFirst()
res = rst.GetRows()
# LOOP THROUGH ROWS
for i in range(len(res)):
# LOOP THROUGH COLUMNS
for j in range(len(res[i])):
print(res[i][j])
# CLOSE AND RELEASE OBJECTS
rst.Close(); conn.Close()
rst = None; conn = None
del rst; del conn
简单的答案是我手动添加每一列以创建完整的行输出,如下所示:
col1 = dbq1.Fields("ID").Value
col2 = dbq1.Fields("Name").Value
col3 = dbq1.Fields("Login").Value
col4 = dbq1.Fields("Email").Value
print(str(col1) + " " + str(col2) + " " str(col3) + " " str(col4))