【发布时间】:2020-12-07 13:53:39
【问题描述】:
我有一个复杂的 SQL Server 查询,我想从 Python 执行它并将结果作为 Pandas DataFrame 返回。
我的数据库是只读的,所以我没有很多选项,就像其他答案所说的那样可以进行不太复杂的查询。
This answer was helpful,但我不断收到TypeError: 'NoneType' object is not iterable
SQL 示例
这不是真正的查询 - 只是为了证明我有临时表。 使用全局临时表,因为我之前使用本地临时表的查询失败:See this question
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
IF OBJECT_ID('tempdb..##temptable') IS NOT NULL DROP TABLE ##temptable
IF OBJECT_ID('tempdb..##results') IS NOT NULL DROP TABLE ##results
DECLARE @closing_period int = 0, @starting_period int = 0
Select col1, col2, col3 into ##temptable from readonlytables
Select * into ##results from ##temptable
Select * from ##results
使用 pyodbc 和 pandas 执行查询
conn = pyodbc.connect('db connection details')
sql = open('myquery.sql', 'r')
df = read_sql_query(sql.read(), conn)
sql.close()
conn.close()
结果 - 全栈跟踪
ypeError Traceback (most recent call last)
<ipython-input-38-4fcfe4123667> in <module>
5
6 sql = open('sql/month_end_close_hp.sql', 'r')
----> 7 df = pd.read_sql_query(sql.read(), conn)
8 #sql.close()
9
C:\ProgramData\Anaconda3\lib\site-packages\pandas\io\sql.py in read_sql_query(sql, con, index_col, coerce_float, params, parse_dates, chunksize)
330 coerce_float=coerce_float,
331 parse_dates=parse_dates,
--> 332 chunksize=chunksize,
333 )
334
C:\ProgramData\Anaconda3\lib\site-packages\pandas\io\sql.py in read_query(self, sql, index_col, coerce_float, params, parse_dates, chunksize)
1632 args = _convert_params(sql, params)
1633 cursor = self.execute(*args)
-> 1634 columns = [col_desc[0] for col_desc in cursor.description]
1635
1636 if chunksize is not None:
TypeError: 'NoneType' object is not iterable
当我在我的数据库中运行查询时,我得到了预期的结果。如果我将查询作为字符串传递,我也会得到预期的结果:
以字符串形式查询
conn = pyodbc.connect('db connection details')
sql = '''
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
IF OBJECT_ID('tempdb..##temptable') IS NOT NULL DROP TABLE ##temptable
IF OBJECT_ID('tempdb..##results') IS NOT NULL DROP TABLE ##results
DECLARE @closing_period int = 0, @starting_period int = 0
Select col1, col2, col3 into ##temptable from readonlytables
Select * into ##results from ##temptable
Select * from ##results
'''
df = read_sql(sql, conn)
conn.close()
我认为这可能与我的查询中的单引号有关?
【问题讨论】:
-
有趣的是,
Select * into ##results from ##temptable除了复制数据还有什么作用?还有为什么要使用全局临时表? -
你能发布完整的堆栈跟踪吗?
-
在
sql = open('myquery.sql', 'r')之后,试试df = read_sql_query(sql.read(), conn) -
@Larnu - 我正在尝试提供我的查询中的内容示例,而没有实际发布查询本身。当我将查询作为字符串传递时,本地临时表不起作用,所以我改为全局(根据这个答案)[stackoverflow.com/questions/37863125/…
-
@Manakin 添加了完整的堆栈跟踪
标签: python sql-server pandas pyodbc