I've read some q&a about "syntax error at or near" but none could solve my issue.
A sample of the error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
psycopg2.ProgrammingError: syntax error at or near "UPDATE"
LINE 1: DECLARE "teste" CURSOR WITHOUT HOLD FOR UPDATE applicant SET...
^
Please, note the ^ right on the UPDATE. I've tested the update script on pgadmin 4 and everything worked fine.
The script is really simple:
UPDATE applicant
SET cv_entities = %s
WHERE id = %s
My code is basically:
def _connect_database():
return psy.connect(
dbname=settings.DATABASE['DBNAME'],
host=settings.DATABASE['HOST'],
port=settings.DATABASE['PORT'],
user=settings.DATABASE['USER'],
password=settings.DATABASE['PASSWORD'],
application_name=settings.env
)
# Connects to database
conn = _connect_database()
# Creats a named cursor
cur = conn.cursor('test')
# Execute
cur.execute(update_script, ('{"json": "test"}', '11125ba0-748f-11e8-b1d0-d8108ee3at21'))
I've explicitly written the script on the execute method as well as the parameters, but I still get the same error:
cur.execute("UPDATE applicant SET cv_entities = 'json here' WHERE id = '11125ba0-748f-11e8-b1d0-d8108ee3at21'")
Note that I even removed the double quotes from the first parameter ('json here')
Am I missing something?!
With
cur = conn.cursor('test')
you are trying to open a server-side cursor. Per the documentation:
cursor(name=None, cursor_factory=None, scrollable=None, withhold=False)
Return a new cursor object using the connection.
If name is specified, the returned cursor will be a server side cursor (also known as named cursor). Otherwise it will be a regular client side cursor.
Use just
cur = conn.cursor()
Server side (named) cursors can be used only for SELECT or VALUES queries. They implement Postgres cursors:
query
A SELECT or VALUES command which will provide the rows to be returned by the cursor.
With named cursors the resulting data is gathered on the server and sent (maybe partialy) to the client when needed (fetched). The data is stored only during the transaction in which the cursor was opened, so commit or rollback releases it.
Client side (unnamed) cursors give the possibility to execute any valid SQL query. A possible resultset is sent to the client immediately after executing the query.
It's possible to use named and unnamed cursors utilizing a single connection but if you want to do this concurrently, you should use two separate connections.
Related
I'm trying to get a list of warnings after a mySQL query, using Django admin. I can see from the documentation here that it's possible to record warnings by setting connection.get_warnings to true. But I can't find anything explaining how to read those warnings.
I do not want to throw an exception - I am deleting items from the database using a DELETE IGNORE statement and want to get all instances of deletions that failed (due to external keys, etc.)
I've tried returning the result of the execute function itself (just gave me a number) and calling fetchwarnings() on the cursor (threw a "Cursor object has no attribute fetchwarnings" error).
I'm still new to both Python and Django. I'm looking through all the documentation I can find but can't find anything that works.
from django.db import connection
query = "{query here}"
connection.get_warnings = True
with connection.cursor() as cursor:
cursor.execute(query) <-- Returns a number
return cursor.fetchwarnings() <-- Throws an error
I have a stored procedure.
calling it via MySQL workbench as follows working;
CALL `lobdcapi`.`escalatelobalarm`('A0001');
But not from the python program. (means it is not throwing any exception, process finish execution silently) if I make any error in column names, then at python I get an error. So it calls my stored procedure but not working as expected. (it is an update query .it needs SAFE update )
Why through the python sqlalchemy this update didn't update any records?
CREATE DEFINER=`lob`#`%` PROCEDURE `escalatelobalarm`(IN client_id varchar(50))
BEGIN
SET SQL_SAFE_UPDATES = 0;
update lobdcapi.alarms
set lobalarmescalated=1
where id in (
SELECT al.id
from (select id,alarmoccurredhistoryid from lobdcapi.alarms where lobalarmpriorityid=1 and lobalarmescalated=0 and clientid=client_id
and alarmstatenumber='02' ) as al
inner join lobdcapi.`alarmhistory` as hi on hi.id=al.alarmoccurredhistoryid
and hi.datetimestamp<= current_timestamp() )
);
SET SQL_SAFE_UPDATES = 1;
END
I call it like;
from sqlalchemy import and_, func,text
db.session.execute(text("CALL escalatelobalarm(:param)"), {'param': clientid})
I suspect the param I pass via code didn't get bind properly?
I haven't called stored procs from SQLAlchemy, but it seems possible that this could be within a transaction because you're using the session. Perhaps calling db.session.commit() at the end would help?
If that fails, SQLAlchemy calls out calling stored procs here. Perhaps try their method of using callproc. Adapting to your use-case, something like:
connection = db.session.connection()
try:
cursor = connection.cursor()
cursor.callproc("escalatelobalarm", [clientid])
results = list(cursor.fetchall())
cursor.close()
connection.commit()
finally:
connection.close()
I have a python program which uses pypyodbc to interact with MSSQL database. A stored procedure is created in MSSQL and is run via python. If I execute the stored procedure only once (via python), there are no problems. However, when it is executed multiple times within a for loop, I get the following error:
pypyodbc.ProgrammingError: ('24000', '[24000] [Microsoft][SQL Server Native Client 11.0]Invalid cursor state')
My python code details are below:
connection_string_prod = 'Driver={SQL Server Native Client 11.0};Server=PSCSQCD1234.TEST.AD.TEST.NET\SQLINS99,2222;Database=Test;Uid=python;Pwd=python;'
connection_prod = pypyodbc.connect(connection_string_prod)
cursor_prod = connection_prod.cursor()
get_files_to_load_query = "Get_Files_To_Load"
files_to_load = cursor_prod.execute(get_files_to_load_query)
for file_name in files_to_load:
load_query = "Load_Query_Stored_Proc #File_Name = '" + file_name + "'"
cursor_prod.execute(load_query)
cursor_prod.commit()
cursor_prod.close()
connection_prod.close()
In some posts it was suggested to use "SET NOCOUNT ON" at the top of the SQL stored procedure. I've done that already and it did not help with this issue.
Below is a code of a simple stored procedure that is causing the issue:
CREATE PROCEDURE [dbo].[Test]
AS
SET NOCOUNT ON
INSERT INTO Test(a)
SELECT 1
Why executing the stored procedure within a for loop only causes an issue?
Please advise.
Thank you!
You are using cursor_prod values to control the for loop and then using that same cursor object inside the loop to run the stored procedure, thus invalidating the previous state of the cursor for controlling the loop. The first iteration of the loop is where the cursor gets overwritten, which is why you don't encounter the error until you try to go through the loop a second time.
You don't need to create a second connection, but you do need to use a second cursor to execute the stored procedure. Or, you could use .fetchall to stuff all of the file names into a files_to_load list and then iterate over that list, freeing up the cursor to run the stored procedure.
I am trying to call dbms_random.seed(42) on my DB, see ref. I need to use python and the JayDeBeApi connector. So far I've only been able to execute select statement without issue. I fail to understand what I am doing wrong.
It seems that JayDeBeApi does not provide the callproc method, so I cannot use it:
AttributeError: 'Cursor' object has no attribute 'callproc'
I've naively tried:
conn = jaydebeapi.connect('oracle.jdbc.driver.OracleDriver',
['jdbc:oracle:thin:#server:1521/dbname', 'user', 'password'])
curs = conn.cursor()
sql="exec dbms_random.seed(42)"
curs.execute(sql)
but this leads to: Error: ORA-00900: invalid SQL statement
I've tried two solutions which seems to have correct syntax, but since the generator is not deterministic, I believe they actually failed:
Using begin/end:
sql="begin dbms_random.seed(42); end;"
curs.execute(sql)
Using call:
sql="{ call dbms_random.seed(42) }"
curs.execute(sql)
So my question is: how do I call dbms_random.seed(42) on Oracle using JayDeBeApi ? As a side question how do I check that a statement has actually failed to execute (no exception was thrown and return value for execute is undefined.)
Update:
In fact the seed initialization is working as expected, since the results are what I expect for:
sql="SELECT DBMS_RANDOM.value FROM dual"
curs.execute(sql)
data = curs.fetchall()
print(data)
However I still see some odd behavior for my random query selection:
SELECT *
FROM (
SELECT *
FROM table
ORDER BY DBMS_RANDOM.RANDOM)
WHERE rownum < 21;
For some reason in the latter case, the DBMS_RANDOM.RANDOM is actually random...
After multiple trial and error, I believe this is just a side effect. Since I was not doing the cleanup pass:
curs.close()
conn.close()
jpype.shutdownJVM()
The query would lead to somewhat undefined behavior. Now that I have a proper cleanup code, I am getting deterministic results when calling multiples times my python script.
I am attempting to call a sproc that wraps T-SQL's sp_send_dbmail procedure. It simply creates the query, and then passes that and a hardcoded subject and recipient to the Microsoft supplied sproc. When running from sql management studio, the sproc executes as expected and I receive an email. From pyodbc, it doesn't send an email. The contents of my sproc look similar to:
declare #qry varchar(MAX)
set #qry = 'select * from table'
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'email#email.com',
#subject = 'my email',
#query = #qry
select * from table
where 1=0
I have also tried toggling the #exclude_query_output, flag but that had no effect. I am invoking that sproc via the following method:
def execute_sproc(query, cnxn):
cursor = cnxn.cursor();
rows = cursor.execute(query)
columns = [column[0] for column in cursor.description]
return pd.DataFrame.from_records(rows, columns=columns)
where the query is simply executing my wrapper sproc. As I mentioned before, the wrapper sproc works when run from the management studio, but no email is sent when called here. I am using the same credentials to access my database in both places. I have also used this function to successfully call other sprocs, but none of them have contained exec statements, nor have they done many of the other things that im sure sp_send_dbmail is doing.
Please let me know if you have any ideas.
Thanks,
Max Goldman
So i think this comes down to a misunderstanding of either the sendmail sproc, pyodbc, or both. I have another method for calling sprocs that edit the database:
def execute_commit_sproc(query, cnxn):
cursor = cnxn.cursor();
cursor.execute(query)
cnxn.commit()
The only difference being that the former expected a result set, whereas the latter makes changes to the db, and uses pyodbc's commit mechanism to save the results. I did not realize the sp_send_dbmail required this to be called in order for the email to be sent. I am still unsure of why (what is getting written to, what pyodbc::commit() is doing under the hood, etc.)