Jalankan file SQL, kembalikan hasilnya sebagai Pandas DataFrame

Saya memiliki kueri SQL Server kompleks yang ingin saya jalankan dari Python dan mengembalikan hasilnya sebagai Pandas DataFrame.

Basis data saya hanya bisa dibaca jadi saya tidak punya banyak opsi seperti jawaban lain untuk membuat pertanyaan yang tidak terlalu rumit.

Jawaban ini sangat membantu, tetapi saya tetap mendapatkan TypeError: 'NoneType' object is not iterable

Contoh SQL

Ini bukan permintaan sebenarnya - hanya untuk menunjukkan bahwa saya memiliki tabel sementara. Menggunakan tabel sementara global karena kueri saya sebelumnya gagal menggunakan tabel temp lokal: Lihat pertanyaan ini

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

Jalankan kueri dengan pyodbc dan pandas

conn = pyodbc.connect('db connection details')

sql = open('myquery.sql', 'r')
df = read_sql_query(sql.read(), conn)
sql.close()
conn.close()

Hasil - Pelacakan Tumpukan Penuh

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

Ketika saya menjalankan kueri di database saya, saya mendapatkan hasil yang diharapkan. Jika saya meneruskan kueri sebagai string, saya juga mendapatkan hasil yang diharapkan:

Kueri sebagai String

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()

Saya pikir ini mungkin ada hubungannya dengan tanda kutip tunggal di dalam permintaan saya?


person terrah27    schedule 18.08.2020    source sumber
comment
Menariknya, apa yang ingin dicapai Select * into ##results from ##temptable, selain menduplikasi data? Juga mengapa tabel sementara global?   -  person Larnu    schedule 18.08.2020
comment
dapatkah Anda memposting jejak tumpukan lengkap?   -  person Umar.H    schedule 18.08.2020
comment
Setelah sql = open('myquery.sql', 'r'), coba df = read_sql_query(sql.read(), conn)   -  person Gord Thompson    schedule 18.08.2020
comment
@Larnu - Saya mencoba memberikan contoh apa yang ada dalam kueri saya tanpa benar-benar memposting kueri itu sendiri. Tabel temp lokal tidak berfungsi ketika saya meneruskan kueri sebagai string jadi saya mengubah ke global (sesuai jawaban ini)[stackoverflow.com/questions/37863125/   -  person terrah27    schedule 18.08.2020
comment
@Manakin Menambahkan pelacakan tumpukan penuh   -  person terrah27    schedule 18.08.2020
comment
@GordThompson Terima kasih telah mengetahui ini - saya sudah memasukkan kode saya tetapi menghilangkannya dalam pertanyaan. Sayangnya hal ini tidak menyelesaikan masalah.   -  person terrah27    schedule 18.08.2020
comment
Baris 7 di pelacakan tumpukan Anda tidak cocok dengan kode sampel Anda. read() masih hilang.   -  person Gord Thompson    schedule 18.08.2020
comment
Saya tidak dapat mereproduksi masalah Anda. Kode ini berfungsi dengan baik untuk saya.   -  person Gord Thompson    schedule 19.08.2020


Jawaban (1)


Saya berhasil.

Saya harus menggunakan variabel global dengan mengganti @ dengan @@ Saya bisa membuat kueri berfungsi seperti yang diharapkan.

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

Pembaruan: Driver ODBC saya sudah sangat usang - setelah memperbarui ke versi terbaru, saya tidak lagi memerlukan tabel atau variabel temp global - dan kueri berjalan jauh lebih cepat.

person terrah27    schedule 21.08.2020