Python: Execute Stored Procedure with Parameters - python

I'm working on a Python script that writes records from a stored procedure to a text file. I'm having issues executing the stored procedure with parameters.
I'm not sure what I could do differently to execute this stored procedure with both parameters. You can see the error I'm getting below.
Any insight would be appreciated.
Here's my code
# Import Python ODBC module
import pyodbc
# Create connection
cnxn = pyodbc.connect(driver="{SQL Server}",server="<server>",database="<database>",uid="<username>",pwd="<password>")
cursor = cnxn.cursor()
# Execute stored procedure
storedProc = "exec database..stored_procedure('param1', 'param2')"
# Loop through records
for irow in cursor.execute(storedProc):
# Create a new text file for each ID
myfile = open('c:/Path/file_' + str(irow[0]) + '_' + irow[1] + '.txt', 'w')
# Write retrieved records to text file
myfile.write(irow[2])
# Close the file
myfile.close()
Here's the error
Traceback (most recent call lst):
File "C:\Path\script.py", line 12, in <module>
for irow in cursor.execute(storedProc):
pyodbc.ProgrammingError: ('42000', "[4200] [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near 'param1'. <102> <SQLExecDirectW>">

I was able to fix the syntax error by removing the parenthesis from the query string.
# Execute stored procedure
storedProc = "exec database..stored_procedure('param1', 'param2')"
should be
# Execute stored procedure
storedProc = "exec database..stored_procedure 'param1','param2'"

This worked for me
query = "EXEC [store_proc_name] #param1='param1', #param2= 'param2'"
cursor.execute(query)

For SQL Server:
cursor.execute('{call your_sp (?)}',var_name)

Related

Python script can't execute SQL Select statement

I'm trying to execute a SQL SELECT statment from Microsoft SQL Server and write that data to an excel spreadsheet.
However, whenever I execute the Python script, I am getting this error:
Traceback (most recent call last):
File "C:\Users\rrw\AppData\Roaming\Python\Python310\site-packages\sqlalchemy\engine\cursor.py", line 955, in fetchone
row = dbapi_cursor.fetchone()
pyodbc.Error: ('HY010', '[HY010] [Microsoft][ODBC Driver 17 for SQL Server]Function sequence error (0) (SQLFetch)')
Traceback (most recent call last):
File "F:\Astro\Python\AstroPy\WriteSQLData.py", line 91, in <module>
for row in rs:
I can see from the error, that it doesn't like the line: for row in rs at the very end of the script. But I can't figure out why.
Is there anything I am missing?
Here is my script:
from sqlalchemy import create_engine
from sqlalchemy.engine import URL
import pyodbc
import pandas as pd
import csv
import configparser
# Get data from configuration ini file
config = configparser.ConfigParser()
config.read('databaseConfig.ini')
destinationFile = config['destination']['fileName']
# Database Connection Code
connection_string = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=ASTROLAB;DATABASE=AstronomyMaps;UID=xyz;PWD=xyz"
connection_url = URL.create(
"mssql+pyodbc", query={"odbc_connect": connection_string})
engine = create_engine(connection_url)
# Simple test query
qry = "SELECT TOP (1000) * FROM [AstronomyMaps].[dbo].[starMapA]"
with engine.connect() as con:
rs = con.execute(qry)
# Write query data to Excel spreadsheet
with open(destinationFile, 'w', newline='') as f:
a = csv.writer(f, delimiter=',')
a.writerow([x[0] for x in cursor.description])
a.writerows(row)
for row in rs:
print(row)
When you exit the context manager (with block) the statement has been executed but the rows haven't been retrieved yet. However, exiting the context manager also "terminates" the connection so for row in rs: throws an error when the ODBC driver tries to call SQLFetch.
You can avoid the error by using .all() to retrieve the rows while still in the with block:
qry = "SELECT TOP (1000) * FROM [AstronomyMaps].[dbo].[starMapA]"
with engine.connect() as con:
rs = con.exec_driver_sql(qry).all()

Python SQL Query Error: TypeError: expecting string or bytes object

I have a python program that makes an SQL query to an Oracle DB using a query saved in a text file *.sql as shown below. I'm getting a "type error" as TypeError: expecting string or bytes object pointing to line with sql = query. I have not been able to solve it. Here is the program:
import pandas as pd
import cx_Oracle
from sys import exit
conn= cx_Oracle.connect('DOMINA/S#U#ex021-orc.corp.mycompany.com:1540/domp_domi_bi')
# READ SQL QUERY FROM FILE
with open(r'C:\Users\Au321103\.spyder-py3\Validation\DOMINA_query.sql') as f:
query = f.readlines()
# IMPORT INTO PANDAS DATA FRAME
try:
df = pd.read_sql(con = conn,
sql = query) # QUERY READ FROM .sql FILE
finally:
conn.close()
df.head()
exit()
Thank you in advance as I'm trying to learn these db queries.

pyodbc insert statement gets error message

I am trying to insert value into SQL SERVER using python.
I wrote my python program as below.
import pyodbc
import subprocess
cnx = pyodbc.connect("DSN=myDSN;UID=myUID;PWD=myPassword;port=1433")
runcmd1 = subprocess.check_output(["usbrh", "-t"])[0:5]
runcmd2 = subprocess.check_output(["usbrh", "-h"])[0:5]
cursor = cnx.cursor()
cursor.execute("SELECT * FROM T_TABLE-A;")
cursor.execute('''
INSERT INTO T_TABLE-A (TEMP,RH,DATE,COMPNAME)
VALUES
(runcmd1,runcmd2,GETDATE(),'TEST_Py')
''')
cnx.commit()
Then get error like below.
# python inserttest.py
Traceback (most recent call last):
File "inserttest.py", line 13, in <module>
''')
pyodbc.ProgrammingError: ('42S22', "[42S22] [FreeTDS][SQL Server]Invalid column name 'runcmd1'. (207) (SQLExecDirectW)")
If I wrote like below, it's OK to insert.
import pyodbc
cnx = pyodbc.connect("DSN=myDSN;UID=myUID;PWD=myPassword;port=1433")
cursor = cnx.cursor()
cursor.execute("SELECT * FROM T_TABLE-A;")
cursor.execute('''
INSERT INTO T_TABLE-A (TEMP,RH,DATE,COMPNAME)
VALUES
(20.54,56.20,GETDATE(),'TEST_P')
''')
cnx.commit()
The command USBRH -t gets temperature and USBRH -h gets humidity. They work well in individual python program.
Does anyone have idea to solve this error?
Thanks a lot in advance.
check the data types returning from these two lines
runcmd1 = subprocess.check_output(["usbrh", "-t"])[0:5]
runcmd2 = subprocess.check_output(["usbrh", "-h"])[0:5]
runcmd1 and runcmd2 should be in 'double' data type since it accepts 20.54.
cursor.execute('''
INSERT INTO T_TABLE-A (TEMP,RH,DATE,COMPNAME)
VALUES
(runcmd1,runcmd2,GETDATE(),'TEST_Py')
''')
won't work because you are embedding the names of the Python variables, not their values. You need to do
sql = """\
INSERT INTO T_TABLE-A (TEMP,RH,DATE,COMPNAME)
VALUES
(?, ?, GETDATE(),'TEST_Py')
"""
cursor.execute(sql, runcmd1, runcmd2)

Passing properly formatted windows pathname to SQL server via PYODBC

I need python to issue a query via pyodbc to insert a .PNG file into a table as a blob. The problem seems to have something to do with how the path to the file is represented. Here's some code:
OutFilePath = 'd:\\DilerBW_images\\'
OutFileName = SubjID+'_'+str(UserID)+'_'+DateTime+'.png'
print OutFilePath+OutFileName
qstring = ('insert into [wpic-smir].[Diler_BW].[Beckwith].[PlotImages](ID, UserID, ImageType, MoodType, ImageIndex, ImageData)'
'select '+str(SubjID)+' as ID, '+str(UserID)+' as UserID,'
'1 as ImageType,'
'NULL as MoodType,'
'NULL as ImageIndex,'
'* from OPENROWSET(Bulk \''+OutFilePath+OutFileName+'\', SINGLE_BLOB) as ImageData')
print qstring
cursor.execute(qstring)
conn.commit()
`
And here's the output:
d:\DilerBW_images\999123_999123_2015-01-20_14-25-07.013000.png
insert into [wpic-smir].[Diler_BW].[Beckwith].[PlotImages](ID, UserID, ImageType, MoodType, ImageIndex, ImageData)select 999123 as ID, 999123 as UserID,1 as ImageType,NULL as MoodType,NULL as ImageIndex,* from OPENROWSET(Bulk 'd:\DilerBW_images\999123_999123_2015-01-20_14-25-07.013000.png', SINGLE_BLOB) as ImageData
Now, here's the error I get:
Traceback (most recent call last):
File "c:\pythonscripts\DilerBW_Plot_Single_report_2_EH.py", line 253, in <module>
cursor.execute(qstring)
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Cannot bulk load because the file "d:\\DilerBW_images\\999123_999123_2015-01-20_14-25-07.013000.png" could not be opened. Operating system error code 3(The system cannot find the path specified.). (4861) (SQLExecDirectW)')
Sorry this is so long. Notice that the file path in the error message includes double backslashes, where the query only includes singles. I have looked extensively at the various methods to build the string (os.path.sep, using a raw string, os.path.join), but it doesn't seem to matter, and I'm not certain the input string is the problem. Again, if I cut and paste the query as it's presented in the output into SSMS and execute it, it works fine.
Thanx.

mysqldb interfaceError

I have a very weird problem with mysqldb (mysql module for python).
I have a file with queries for inserting records in tables. If I call the functions from the file, it works just fine; but when trying to call one of the functions from another file it throws me a
_mysql_exception.InterfaceError: (0, '')
I really don't get what I'm doing wrong here..
I call the function from buildDB.py :
import create
create.newFormat("HD", 0,0,0)
The function newFormat(..) is in create.py (imported) :
from Database import Database
db = Database()
def newFormat(name, width=0, height=0, fps=0):
format_query = "INSERT INTO Format (form_name, form_width, form_height, form_fps) VALUES ('"+name+"',"+str(width)+","+str(height)+","+str(fps)+");"
db.execute(format_query)
And the class Database is the following :
import MySQLdb
from MySQLdb.constants import FIELD_TYPE
class Database():
def __init__(self):
server = "localhost"
login = "seq"
password = "seqmanager"
database = "Sequence"
my_conv = { FIELD_TYPE.LONG: int }
self.conn = MySQLdb.connection(host=server, user=login, passwd=password, db=database, conv=my_conv)
# self.cursor = self.conn.cursor()
def close(self):
self.conn.close()
def execute(self, query):
self.conn.query(query)
(I put only relevant code)
Traceback :
Z:\sequenceManager\mysql>python buildDB.py
D:\ProgramFiles\Python26\lib\site-packages\MySQLdb\__init__.py:34: DeprecationWa
rning: the sets module is deprecated
from sets import ImmutableSet
INSERT INTO Format (form_name, form_width, form_height, form_fps) VALUES ('HD',0
,0,0);
Traceback (most recent call last):
File "buildDB.py", line 182, in <module>
create.newFormat("HD")
File "Z:\sequenceManager\mysql\create.py", line 52, in newFormat
db.execute(format_query)
File "Z:\sequenceManager\mysql\Database.py", line 19, in execute
self.conn.query(query)
_mysql_exceptions.InterfaceError: (0, '')
The warning has never been a problem before so I don't think it's related.
I got this error when I was trying to use a closed connection.
Problem resolved.. I was initializing the database twice.. Sorry if you lost your time reading this !
I couldn't get your setup to work. I gives me the same error all the time. However the way you connect to and make queries to the db with the query seems to be "non-standard".
I had better luck with this setup:
conn = MySQLdb.Connection(user="user", passwd="******",
db="somedb", host="localhost")
cur = conn.cursor()
cur.execute("insert into Format values (%s,%s,%s,%s);", ("hd",0,0,0))
This way you can take advantage of the db modules input escaping which is a must to mitigate sql injection attacks.

Categories