Reputation: 151
Pyodbc is returning TypeError: 'NoneType' object is not iterable. Although, when I copy and paste the sql f string into sql server, I get millions of records.
cnxn = pyodbc.connect('DRIVER={SQL Server};'
'SERVER=server;'
'DATABASE=db;')
sql=f"exec dbo.storedproc '{AdmitDate_Start}','{AdmitDate_End}','{RelativeStartDate}','{RelativeEndDate}'"
df=pd.read_sql(sql,cnxn)
I was able to successfully execute another stored procedure from the same location (server and db). However, that stored proc doesn't require that I pass the four variables above. I also tried creating the sql statement with Declare and passing in the variables. RelativeStartDate and RelativeEndDate can be null.
sql='''declare @AdmitDate_Start datetime = '''+"'"+ads+"'"+''';declare @AdmitDate_End datetime = '''+"'"+ade+"'"+''';declare @RelativeStartDate VARCHAR(20);declare @RelativeEndDate VARCHAR(20);exec dbo.storedproc @AdmitDate_Start, @AdmitDate_End,@RelativeStartDate,@RelativeEndDate;'''
This also returned 0 records in python, but ran fine in SQL Server.
This led me to trying a few different drivers, but these wouldn't connect:
['SQL Server Native Client 11.0', 'ODBC Driver 13 for SQL Server', 'ODBC Driver 17 for SQL Server']
Any ideas as to what may be the cause of returning None records and how to fix?
Upvotes: 0
Views: 785
Reputation: 151
the sql script did not contain "set no count on;" When adding this line to before execute, it worked.
sql=f"set no count on;exec dbo.storedproc '{AdmitDate_Start}','{AdmitDate_End}','{RelativeStartDate}','{RelativeEndDate}'"
Upvotes: 1
Reputation:
The following works here at my end. (Note the use of params.)
import pyodbc
import pandas as pd
MSSQL = {
"database": "***",
"password": "***",
"server": "***",
"user": "***"
}
SQL = 'EXEC dbo.delete_me @lat = ?, @lon = ?, @InvoiceNumber = ?'
def get_connection(server, database, user, password):
cs = f'DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={server};DATABASE={database};UID={user};PWD={password}'
return pyodbc.connect(cs)
if __name__ == '__main__':
with get_connection(**MSSQL) as conn:
df = pd.read_sql(SQL, conn, params=(43.6010067, -79.6838868, 123456))
print(df)
where dbo.delete_me is defined as
create procedure [dbo].[delete_me]
@lat decimal(18,12)
,
@lon decimal(18,12)
,
@InvoiceNumber nvarchar(15)
as
begin
set nocount on;
select @lat as latitude, @lon as longitude, @InvoiceNumber as invoice
end
The set nocount on;
does not affect the python code in anyway.
Upvotes: 0