执行SQL文件,返回结果为Pandas DataFrame



我有一个复杂的SQL Server查询,我想从Python执行它,并将结果作为Pandas DataFrame返回。

我的数据库是只读的,所以我没有像其他答案那样的很多选项来进行不那么复杂的查询。

这个答案很有帮助,但我一直得到TypeError: 'NoneType' object is not iterable

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

使用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:ProgramDataAnaconda3libsite-packagespandasiosql.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:ProgramDataAnaconda3libsite-packagespandasiosql.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()

我认为这可能与我的查询中的单引号有关?

我让它工作起来了。

我不得不使用全局变量,将@替换为@@。我能够使查询按预期工作。

DECLARE @@closing_period int = 0, @@starting_period int = 0

更新:我的ODBC驱动程序已经非常过时了——更新到最新版本后,我不再需要全局临时表或变量——查询运行速度明显加快。

相关内容

  • 没有找到相关文章

最新更新