5

I am trying to run a SQL command using pyodbc in python. in which SQL command contains multiple SELECT commands and IF statements.

but I am getting an error as follows

columns = [col_desc[0] for col_desc in cursor.description]
TypeError: 'NoneType' object is not iterable

import pyodbc
import pandas as pd
conn = pyodbc.connect("DRIVER={SQL Server};"
                "SERVER=server_name;"
                "DATABASE=master;"
                "Trusted_Connection=yes;")
cursor = conn.cursor()
script="""

If object_id ('tempdb..#Temp1')is not null
drop table #Temp1
Select distinct  a1.some_ID into #Temp1
from DOC.dbo.Document_tbl (NOLOCK)a1
from #Temp1 a1
If object_id ('tempdb..#Temp2')is not null
Drop table #Temp2
select distinct v2.some_data
into #Temp2 from tbl_name (nolock) v2 

If object_id ('tempdb..#Results')is not null
drop table #Results
select distinct a1.*,b1.####
into #Results
from #Temp1 a1
left join #Temp2 b1 on a1.## = b1.##
Select * from #Results
"""

df = pd.read_sql(script, cnxn)
writer = pd.ExcelWriter('result.xlsx')
df.to_excel(writer, sheet_name ='bar')
writer.save()
3
  • 1
    The error says that there is nothing in the cursor, basically, it means that your returned nothing. Commented Sep 10, 2019 at 8:35
  • Please remove those NOLOCK query hints unless you understand exactly why you need them and the risks of using them, including retrieving invalid data and data that does not exist Commented Sep 10, 2019 at 9:29
  • Thank you Gord Thompson Commented Sep 10, 2019 at 11:45

2 Answers 2

5

SQL command text that contains multiple SQL statements is called an anonymous code block. An anonymous code block can return multiple results, where each result can be

  • a row count,
  • a result set containing zero or more rows of data, or
  • an error.

The following example fails ...

sql = """\
SELECT 1 AS foo INTO #tmp;
SELECT * FROM #tmp;
"""
df = pd.read_sql_query(sql, cnxn)
# TypeError: 'NoneType' object is not iterable

... because the first SELECT ... INTO returns a row count before the second SELECT returns its result set.

The fix is to start the anonymous code block with SET NOCOUNT ON; which suppresses the row count and only returns the result set:

sql = """\
SET NOCOUNT ON;
SELECT 1 AS foo INTO #tmp;
SELECT * FROM #tmp;
"""
df = pd.read_sql_query(sql, cnxn)
# no error
Sign up to request clarification or add additional context in comments.

Comments

3

For anyone else who is still getting this error, I have found that for some statements (A window function that aggregated null values) I also need to include SET ANSI_WARNINGS OFF;.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.