Error when calling a procedure from pyodbc - python

This is my first question here. So, I am sorry if it is repeated or the formatting is off. I searched through other questions and the error is common but appears on multiple situations.
I have a very simple python code where I want to execute a procedure in MSSQL from pyodbc.
import pyodbc
conn = pyodbc.connect(r'DSN=myDSN')
cursor = conn.cursor()
query = r'{call myproc}'
cursor.execute(query)
I am using call instead of exec after reading that ODBC uses call for executing procedures in MSSQL.
The error I am getting is the following:
Traceback (most recent call last):
File "myscript.py", line 26, in <module>
cursor.execute(query)
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][SQL Server Native Client 11.0][SQL Server]The current transaction has aborted, and any pending changes have been rolled back. Cause: A transaction in a rollback-only state was not explicitly rolled back before a DDL, DML or SELECT statement. (111233) (SQLExecDirectW)')
Thanks for the help

In case someone is having the same issue. I was able to find out what the problems was. When you open a connection with DSN, the autocommit is set to False. For some reason, this should be True for the code to work (this depends largely on what I was doing on MSSQL).
import pyodbc
conn = pyodbc.connect(r'DSN=myDSN', autocommit=True)
cursor = conn.cursor()
query = r'{call myproc}'
cursor.execute(query)
This runs well!

Here are two examples on how you can execute a stored proc in MS SQL Server through pyodbc:
Passing a NULL, and the VARCHAR 'tallen' as positional parameter variables:
cursor.execute('EXEC usp_get_user_data ?, ?', None, 'flipperpa')
Passing two VARCHAR values as named parameter variables:
cursor.execute('EXEC usp_get_user_data #user_full_name = ?, #user_username = ?', 'flip', 'flipperpa')
Then to loop through the returned data:
rows = cursor.fetchall()
for row in rows:
# Do stuff
print(row.user_id)
Good luck!

I had issue with executing the Stored procedure using the SQL server 2008. The first step I did is to go to control panel > Administrative tools > Data Sources (ODBC) > add the driver
The only change I made in my python code is use "{call procdev_2017}". I got an error when I tried using exec instead of call
import pyodbc
conn = pyodbc.connect(driver='{SQL Server Native Client 11.0}', server='XXXXXXX', database='XXX',
trusted_connection='yes', autocommit=True)
bepcur = conn.cursor()
ipcur.execute("{call procdev_2017}")

Related

update statement under pyodbc issue

I am currently developing a program in python that interacts with multiple database. I am using pyodbc to connect, and execute queries. One of the database is an azure database. I noticed sometimes the sent data is not updated in the database although the program run successfully and no error was thrown. Is there any practices that i should follow to make sure this doesn't happen or is this related to my code or db connection issue? I am a beginner. Would appreciate everyone's help thank you!
Also is the .commit() line should be run after every sql run?
The program should be updating a row of data in the database based on a condition, this particular query sometimes doesn't take effect, but no error was thrown. I also executed multiple queries after that, no issue was found for the next queries. It is successfully executed.
the query is a simple query which is
UPDATE DraftVReg SET VRStatus = 'Potential Duplicate Found' WHERE RowID = ?
I tried to reproduce your scenario on my end and was able to update the SQL row in the Azure SQL DB with Pyodbc module.
Yes, Its very necessary to use
conn.commit
to commit your changes inside a database after you perform operations such as Update or Insert inside Azure SQL DB programmatically.
1) Fetch Data with Select statement.
I was able to fetch the Table’s data successfully with Select * from ‘Tablename’ query inside pyodbc code before I try UPDATE statement.
import pyodbc
conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};''SERVER=tcp:sqlservernamesql.database.windows.net,1433;''DATABASE=databasename; UID=siliconuser;PWD=Password;')
#conn.commit()
cursor = conn.cursor()
cursor.execute('Select * FROM StudentReviews')
#conn.commit()
for i in cursor:
print(i)
cursor.close()
conn.close()
Result:-
2) UPDATE the rows require conn.commit()
Code :-
import pyodbc
conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};''SERVER=tcp:siliconserversql.database.windows.net,1433;''DATABASE=silicondb; UID=userid; PWD=Password;')
cursor = conn.cursor()
#cursor.execute('Select * FROM StudentReviews')
cursor.execute("UPDATE StudentReviews SET ReviewTime = ('7') WHERE ReviewText = ('SQL DB')")
conn.commit()
cursor.close()
conn.close()
Result:-
Update statement Executed successfully and the Table Row was updated in Azure SQL, Refer Below :-
3) With autocommit=true
Thank you #Gord thompson for the comment and suggestion!
Code :-
import pyodbc
conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};''SERVER=tcp:siliconserversql.database.windows.net,1433;''DATABASE=silicondb; UID=username; PWD=Password;', autocommit=True)
#conn.commit()
cursor = conn.cursor()
cursor.execute("UPDATE StudentReviews SET ReviewTime = ('8') WHERE ReviewText = ('SQL DB')")
cursor.close()
conn.close()
Results :- With autocommit=true, You do not need to add conn.commit everytime you update the SQL DB.

python pyodbc: Closing the cursor before conn.commit()?

I have an issue with inserting data into a database using the python package pyodbc and since I am pretty new to pyodbc & databases in general, I might lack some basic understanding.
I open a connection, and then I want the execute my query.
Actually, in this query I call a stored procedure (which I didn't write and I am not allowed to change!).
This procedure does "one or two" inserts. When I use pyodbc like this
conn = pyodbc.connect(connection_string)
with conn:
c = conn.cursor()
c.execute("{call input_procedure('some','parameters','to','insert')}")
OR
conn = pyodbc.connect(connection_string)
c = conn.cursor()
c.execute("{call input_procedure('some','parameters','to','insert')}")
conn.commit()
I get the following error message:
pyodbc.Error: ('HY000', "[HY000] [MySQL][ODBC 8.0(a) Driver]Commands out of sync; you can't run this command now (2014) (SQLEndTran(SQL_COMMIT))")
As far as I understood, this error message might be due to executing more than one insert within the called procedure. When I print the return of the execute command I become the following: (' ', )
When I instead close the cursor, before doing the commit, everything works fine. Like this:
conn = pyodbc.connect(connection_string)
c = conn.cursor()
c.execute("{call input_procedure('some','parameters','to','insert')}")
c.close()
conn.commit()
I really don't understand what's happening here.
Is there an explanation for this behaviour? Is closing the cursor before doing the commit save?
Thanks a lot for your help!
You seem to have encountered a quirk in MySQL Connector/ODBC's handling of result sets from a stored procedure. For this example procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `input_procedure`(IN `p1` VARCHAR(50))
MODIFIES SQL DATA
BEGIN
INSERT INTO table1 (txt) VALUES (p1);
SELECT '' AS foo;
END
this Python code
crsr = cnxn.cursor()
crsr.execute("{call input_procedure('thing')}")
cnxn.commit()
throws the "Commands out of sync" error, whereas this code
crsr = cnxn.cursor()
crsr.execute("{call input_procedure('thing')}")
while crsr.nextset():
pass
cnxn.commit()
does not.

How to commit stored procedure execution by using pyodbc

I am trying to execute stored procedure by using pyodbc in databricks, after executing SP I tried to commit the connection but, commit is not happening. Here I am giving my code, please help me out from this issue.
import pyodbc
#### Connecting Azure SQL
def db_connection():
try:
username = "starsusername"
password = "password-db"
server = "server-name"
database_name = "db-name2"
port = "db-port"
conn=pyodbc.connect('Driver={ODBC Driver 17 for SQL server};SERVER=tcp:'+server+','+port+';DATABASE='+ database_name +';UID='+ username +';PWD='+ password)
cursor=conn.cursor()
return cursor, conn
except Exception as e:
print("Faild to Connect AZURE SQL: \n"+str(e))
cursor, conn = db_connection()
# conn1.autocommit=True
cursor.execute("delete from db.table_name")
cursor.execute("insert into db.table_name(BUSINESS_DATE) values('2021-10-02')")
cursor.execute("exec db.SP_NAME '20211023'")
conn.commit()
conn.close()
here I am commiting connection after SP excution. deletion and insertion is not happening at all. and I tried with cursor.execute("SET NOCOUNT ON; exec db.SP_NAME '20211023'") but it's also not working.
Thanks in Advance
If you check this document on pyodbc, you will find that -
To call a stored procedure right now, pass the call to the execute method using either a format your database recognizes or using the ODBC call escape format. The ODBC driver will then reformat the call for you to match the given database.
Note that after connection is set up or done, try doing conn.autocommit = True before calling your SP and it will help. By default it is false.
Executing the Stored Procedure.
You will be able to execute your stored procedure if you follow the below code snippet.
cursor = conn.cursor()
conn.autocommit = True
executesp = """EXEC yourstoredprocedure """
cursor.execute(executesp)
conn.commit()
Delete the Records in SQL Server
You can delete record as shown in the below example.
...#just an example
cursor.execute('''
DELETE FROM product
WHERE product_id in (5,6)
''')
conn.commit()
Don’t forget to add conn.commit() at the end of the code, to ensure that the command would get executed.
Insert record in SQL Server
The below snippet show how we can do the same.
...#just an example
cursor.execute("INSERT INTO EMP (EMPNO, ENAME, JOB, MGR) VALUES (535, 'Scott', 'Manager', 545)")
conn.commit()
I will suggest you to read the for following document for more information.
Delete Record Documentation.
Insert Record Document

How to connect spyder to a postgres database?

I am using Python with spyder and would like to directly connect to the our postgres datawarehouse to directly query data from there for further analysis.
This is what I found under the following link:
[https://www.psycopg.org/docs/]
import psycopg
Connect to your postgres DB
conn = psycopg.connect("dbname=*** user=***")
Open a cursor to perform database operations
cur = conn.cursor()
Execute a query
cur.execute("SELECT * FROM my_data")
Retrieve query results
records = cur.fetchall()
However, I get the following error message:
runfile('C:/Users/.../.spyder-py3/untitled2.py', wdir='C:/Users/.../.spyder-py3')
Traceback (most recent call last):
File "C:\Users....spyder-py3\untitled2.py", line 9, in
import psycopg
ModuleNotFoundError: No module named 'psycopg'
https://www.psycopg.org/docs/ -> this is what you are looking for.
Next step might be using pandas read_sql() to load the sql table into to your variable exploirer if it is not too big.
Does this help?
Posting this in the Spyder Editor actually worked to establish a connection with the PostgreSQL Database:
import psycopg2
connection = psycopg2.connect(user="...",
password="...",
host="...",
port="...",
database="...")
cursor = connection.cursor() cursor.execute("SELECT * FROM data.table25 limit 5")
After running the above command you can check for your rows with:
rows=cur.fetchall()

pyodbc does not throw on SQL Server error

I am trying to use pyodbc (with Python 2.7) to call a stored procedure to insert records into a SQL Server 2012 table. I am passing a temporary table.
I dumped out my sql and when executed through the SQL Server Management console, it generated the following Foreign Key error:
Msg 547, Level 16, State 0, Procedure spInsertBondTickerValues, Line 26
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__BondTickerValue__756D6ECB".
The conflict occurred in database "QuantDev", table "dbo.Tickers".
The statement has been terminated.
However, pyodbc did not raise an exception. How would I test the resulting cursor or connection to know that a problem occurred, and how do I get the error message?
Thank you very much.
EDIT Here is the full sql text:
DECLARE #rawTbl [dbo].TickerValueTableType
INSERT INTO #rawTbl (Ticker, BBName, LastValue, ValueTime, SourceDescr) VALUES
('IBM', 'Equity', 179.230000, '2013-11-01 00:00:00.000000', 'Bloomberg'),
('SPX', 'Index', 1803.710000, '2013-12-10 00:00:00.000000', 'Bloomberg')
EXEC [dbo].spInsertBondTickerValues #rawTbl
EDIT 2 Here is the relevant Python code:
def execSQLwithCommit(self, sql):
cursor = self.conn.cursor()
cursor.execute(sql)
self.conn.commit()
where the connection has been previously made via
self.conn = pyodbc.connect(app = appName,
driver = '{SQL Server Native client 11.0}',
server = server,
database = db,
Trusted_Connection = 'yes')
I was able to recreate your issue using the following code, which fails silently:
import pyodbc
cnxn = pyodbc.connect('DSN=myDb;')
cursor = cnxn.cursor()
sql = """
DECLARE #rawTbl dbo.ClientAddressInputType;
INSERT INTO #rawTbl (ClientID, Addr1) VALUES
(2, 'higgy'),
(3, 'jiggy');
EXEC dbo.AddClientAddress #rawTbl
"""
cursor.execute(sql)
cursor.commit()
cnxn.close()
However, I can get the code to throw the appropriate IntegrityError exception by simply adding SET NOCOUNT ON; at the beginning of the sql string:
import pyodbc
cnxn = pyodbc.connect('DSN=myDb;')
cursor = cnxn.cursor()
sql = """
SET NOCOUNT ON;
DECLARE #rawTbl dbo.ClientAddressInputType;
INSERT INTO #rawTbl (ClientID, Addr1) VALUES
(2, 'higgy'),
(3, 'jiggy');
EXEC dbo.AddClientAddress #rawTbl
"""
cursor.execute(sql)
cursor.commit()
cnxn.close()
which results in
Traceback (most recent call last):
File "C:\Users\Gord\Desktop\pyOdbc.py", line 12, in <module>
cursor.execute(sql)
IntegrityError: ('23000', '[23000] [Microsoft][SQL Server Native Client 10.0][SQL Server]The INSERT statement conflicted with the FOREIGN KEY constraint "FK_ClientAddresses_Clients". The conflict occurred in database "myDb", table "dbo.Clients", column \'ClientID\'. (547) (SQLExecDirectW); [01000] [Microsoft][SQL Server Native Client 10.0][SQL Server]The statement has been terminated. (3621)')

Categories

Resources