Output parameters are not populated - python

I have the following code:
conn = pymssql.connect(server, user, password, database)
cursor = conn.cursor()
id_new_field = pymssql.output(int)
res = cursor.callproc('NewField', ('Test',id_new_field))
conn.commit()
conn.close()
print(id_new_field.value)
print(res)
Unfortunately my output parameter isn't populated with the id of the field, although the stored procedure is executed correctly. The output ist always 'None'.
I think the problem is, that autocommit ist set to false in my example, am i right?
But i can't set autocommit to true because the stored procedure is raising an error when it isn't executed inside a transaction (It's a vendor SP and i can't alter the SP).
So, my workarount for now is, to use .execute() instead of .callproc() and writing raw sql into my python script. It's awful. ;)
Is there any chance to use .callproc() with autocommit = false?
Or do i have to do it completely different?

I also got None when I did
print(id_new_field.value)
but I was able to retrieve the value by simply indexing into res tuple:
print(res[1])
(Tested with Python 2.7.11 and pymssql 2.1.1.)

Related

Python and mySQL rowcount not behaving as expected

I am teaching myself python and have a function called mysqltimedcheck()
This executes a very basic mySQL SELECT statement and returns the rowcount.
If i cange the value of 'shown' from 0 to 1 in the mysql table (while the script is running) for example the rowcount does not change.
I can see when debugging that it reruns the cursor.execute line again but still prints an old value
here is my function:
def mysqltimedcheck():
cursor = mydb.cursor(buffered=True)
window.after(1500, mysqltimedcheck)
cursor.execute("SELECT * FROM alerts WHERE shown = 0")
rc = cursor.rowcount
print(rc)
If i restart my test application then it pulls the correct rowcount value but changing this value while running does not show as correct.
I feel im missing something very basic.
Thanks for your help
All credit to #LabibaKanij
adding mydb.commit() worked correctly and allowed me to change the value in the table and it changed for my script without restarting.

why the stored procedure called from sqlalchemy is not working but calling from workbench is working?

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()

Using substitution in Pythhon with mysql cursor method

I have multiple databases named in a pattern. Database names,
for example: house_1, house_2, house_2
In my Python(2.7) script, a variable gets passed (house_id). That variable contains 1, 2 or 3, etc.
I need to be able to establish a connection to the appropriate database depending on the house_id.
Individually, this looks like:
house1_db = mysql.connector.connect(user="root", password="mypassword!", host="127.0.0.1", database="house_1")
cursor = house1_db.cursor
It seems really clumsy to me to do it this way. I'm looking for a way to do the equivalent of string substitution.
So, script gets passed house_id = 6
And then:
house%d_db = mysql.connector.connect(user="root", password="mypassword!", host="127.0.0.1", database="house_%d") % house_id
cursor = house%d_db.cursor % house_id
I know the above examples with %d are wrong. But I think it illustrates what I am trying to accomplish. Maybe not.
I've been playing around with string substitution mainly, and am getting errors like: "
String Object has no attribute cursor".
Thanks in advance. I know this is a vague question. I'm getting rather frustrated with it!
Create a function and pass db_name to it.
Using with closes your connection and cursor automatically.(No need to close it explicitly like conn.close(), cursor.close() )
Try this,
def create_conn(db_name):
return mysql.connector.connect(user="root", password="mypassword!", host="127.0.0.1", database=db_name)
with create_conn('house_1') as conn:
with conn.cursor() as cursor:
...

Call procedure on Oracle 11.2.0 via JayDeBeApi in Python

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.

calling msdb.sp_send_dbmail via pyodbc

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.)

Categories

Resources