Execute a PL/SQL function (or procedure) from SQLAlchemy - python

I have a legacy PL/SQL function:
getlogin(p_username in varchar2, p_password in varchar2) return boolean;
How can I execute this from SQLAlchemy and get the return value?
A naive approach like this doesn't seem to work:
result = DBSession.execute('getlogin(:username, :password)',
{'username':request.POST['username'],'password':request.POST['password']});
# extract return value from result
From the logs I see this error:
File "../env/lib/python3.3/site-packages/SQLAlchemy-0.8.0-py3.3.egg/sqlalchemy/engine/base.py", line 871, in _execute_context
context)
File "../env/lib/python3.3/site-packages/SQLAlchemy-0.8.0-py3.3.egg/sqlalchemy/engine/default.py", line 322, in do_execute
cursor.execute(statement, parameters)
cx_Oracle.DatabaseError: ORA-00900: invalid SQL statement
I can see it looks like the SQL interpreter is being invoked and not the PL/SQL interpreter, but I'm not sure on the next steps.

You'll probably have to provide a PL/SQL block to your execute call:
result = DBSession.execute('begin getlogin(:username, :password); end;',
{'username':request.POST['username'],'password':request.POST['password']});
This SO question on SQLAlchemy + Oracle SP might also help.

If you're using .execute() on a connection method then you need a valid SQL statement. If getlogin is a function, this requires a SELECT:
result = DBSession.execute('select getlogin(:username, :password) from dual'
, {'username' : request.POST['username']
,'password' : request.POST['password']});
As the error states, your SQL statement is invalid.

Related

How Can My sqllite3 interaction be fixed?

I'm trying to get an admin account to edit a 'rank' (basically access level) for one of the profiles in my data-base. The error is:
Traceback (most recent call last):
File "U:/A-level Computor Science/Y12-13/SQL/sqlite/Databases/ork task/Python for SQL V_2.py", line 154, in <module>
main()
File "U:/A-level Computor Science/Y12-13/SQL/sqlite/Databases/ork task/Python for SQL V_2.py", line 9, in main
start_menu()
File "U:/A-level Computor Science/Y12-13/SQL/sqlite/Databases/ork task/Python for SQL V_2.py", line 22, in start_menu
login()
File "U:/A-level Computor Science/Y12-13/SQL/sqlite/Databases/ork task/Python for SQL V_2.py", line 72, in login
Mek_menu()
File "U:/A-level Computor Science/Y12-13/SQL/sqlite/Databases/ork task/Python for SQL V_2.py", line 108, in Mek_menu
where Uzaname = %s""" % (NewRank, Findaname))
sqlite3.OperationalError: unrecognized token: "0rk_D4T4B453"`
The code that seems to be the problem is:
cursor.execute(""" update 0rk_D4T4B453.Da_Boyz
set Rank = %s
where Uzaname = %s""" % (NewRank, Findaname))
Originally, it was all on one line and it didn't work, and now I've tried it on multiple lines and it still doesn't work. So I checked here to see if anyone could help.
EDIT1: Thanks for the suggestions. None of them have fixed the code, but I've narrowed the problem code to: where Uzaname = %s""" % (NewRank, Findaname))
Unless you use ATTACH, SQLite (a file-level database) does not recognize other databases. Usually server-level databases (Oracle, Postgres, SQL Server, etc.) use the database.schema.table reference. However, in SQLite the very database file you connect to is the main database in scope. But ATTACH allows you to connect to other SQLite databases and then recognizes database.table referencing.
Additionally, for best practices:
In sqlite3 and any other Python DB-APIs, use parameterization for literal values and do not format values to SQL statement.
In general Python, stop using the de-emphasized (not deprecated yet) string modulo operator, %. Use str.format or more recent F-string for string formatting. But neither is needed here.
Altogether, if you connect to the 0rk_D4T4B453 database, simply query without database reference:
conn = sqlite3.connect('/path/to/0rk_D4T4B453.db')
cursor = conn.cursor()
# PREPARED STATEMENT WITH QMARK PLACEHOLDERS
sql = """UPDATE Da_Boyz
SET Rank = ?
WHERE Uzaname = ?"""
# BIND WITH TUPLE OF PARAMS IN SECOND ARG
cursor.execute(sql, (NewRank, Findaname))
conn.commit()
If you do connect to a different database, call ATTACH. Here also, you can alias other database with better naming instead of number leading identifier.
cursor.execute("ATTACH '/path/to/0rk_D4T4B453.db' AS other_db")
sql = """UPDATE other_db.Da_Boyz
SET Rank = ?
WHERE Uzaname = ?"""
cursor.execute(sql, (NewRank, Findaname))
conn.commit()
cur.execute("DETACH other_db")

Uploading image to mariadb database

I'm new to sql so maybe this is just a beginner's mistake, but after trying some solutions I found here and there I'm still unable to solve this problem. I'm trying to upload an image to a mariadb database through a python script which looks like this:
import mysql.connector
path=input("File to upload: ")
with open(path,'rb') as f:
fileData=f.read()
query=f"UPDATE emp SET image={fileData} WHERE empId=1;"
db=mysql.connector.connect(...)
myCursor=db.cursor()
myCursor.execute(query)
myCursor.close()
db.close()
print(f"Uploaded {path} to the database...")
However, when the code reaches myCursor.execute(query) I get the following error:
Traceback (most recent call last):
File "webSqlSampleClient.py", line 16, in <module>
myCursor.execute(query)
File "/home/asriel/.local/lib/python3.8/site-packages/mysql/connector/cursor.py", line 551, in execute
self._handle_result(self._connection.cmd_query(stmt))
File "/home/asriel/.local/lib/python3.8/site-packages/mysql/connector/connection.py", line 490, in cmd_query
result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
File "/home/asriel/.local/lib/python3.8/site-packages/mysql/connector/connection.py", line 395, in _handle_result
raise errors.get_exception(packet)
mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xe1\x00'' at line 1
What's wrong with my code? The rest of the query seems correct as I've used the very same UPDATE statement with other non-image values successfully.
Thank you in advance for the help.
-Update:
As #tadman suggested, I've used %s as a placeholder in my sql query, so the new code looks like this:
query="UPDATE emp SET image=%s WHERE empId=1"
db=mysql.connector.connect(...)
myCursor=db.cursor()
myCursor.execute(query, (fileData,))
myCursor.close()
db.close()
The code above doesn't run into any exceptions and prints the intended output, however, when I execute the following SQL statement in my SQL client:
SELECT image
FROM emp
WHERE empId = 1;
it says that the value for image is NULL.
What's wrong now? image is a blob, in case that's not clear.
Ok, so I've just got it to work:
the answer I used to solve the first problem was #tadman's answer (which is in the question's comments). The problem I had with the database not updating its values was solved by adding db.commit() (I forgot that, silly mistake). Thanks for all of your helpful comments anyways!

SQL statement failing to execute in Python CGI

I have an update statement in my database that is not executing. As far as I am aware, it is syntactically correct. I used this app to verify the syntax. The except block is all that is being executed and I do not understand why.
Here is the code:
for res_posts in list_of_response_ids:
temp_str = res_posts[0] # first element of res_posts tuple is string
temp_str += ":" + str(output[0])
try:
sql = "UPDATE POST SET res_post_id = %s WHERE post_id = %d;" % (str(temp_str), int(res_posts[1]))
cursor.execute(sql)
except:
print "uh oh"
I can post more code if this is not enough information.
EDIT: Following Jacob's advice, I used raise and got the following error:
Traceback (most recent call last):
File "post.cgi", line 93, in <module>
cursor.execute(sql)
File "/usr/lib64/python2.6/site-packages/MySQLdb/cursors.py", line 173, in execute
self.errorhandler(self, exc, value)
File "/usr/lib64/python2.6/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':37 WHERE post_id = 8' at line 1")
Thank you so much!
Based on your traceback, there is something wrong with the type of entry you are using for the res_post_id or post_id. Currently you are not passing a representation of the res_post_id string, but a literal string. If res_post_id is a string in your DB Schema, I would recommend using %r like so:
sql = "UPDATE POST SET res_post_id = %r WHERE post_id = %d;" % (str(temp_str), int(res_posts[1]))
This will properly quote your res_post_id value for insertion.
So your statement should change from this:
UPDATE POST SET res_post_id = :37 WHERE post_id = 8;
...to this:
UPDATE POST SET res_post_id = ':37' WHERE post_id = 8;

Mysql query using python

I'm using python 3.x and mysql.connector to access a Mysql database. I'm having an issuing with querying the database.
When I run the following query, I get the correct result:
cursor.execute("SELECT idx FROM db WHERE name = 'John Smith'")
When I try and run the following query I get an error:
cursor.execute("SELECT idx FROM db WHERE name = %s",'John Smith')
File "<input>", line 1, in <module>
File "C:\Python34\lib\site-packages\mysql\connector\cursor.py", line 515, in execute
self._handle_result(self._connection.cmd_query(stmt))
File "C:\Python34\lib\site-packages\mysql\connector\connection.py", line 488, in cmd_query
result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
File "C:\Python34\lib\site-packages\mysql\connector\connection.py", line 395, in _handle_result
raise errors.get_exception(packet)
mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%s' at line 1
I've tried running the following query instead, but it appears that the query searches for "%s" not the string "John Smith"
cursor.execute("SELECT idx FROM db WHERE name = '%s'",'John Smith')
I'm not sure if the error is due to the fact that I'm using a string with spaces in it or not, but I haven't been able to solve the problem.
q="SELECT idx FROM db WHERE name = %s";
cursor.execute(q,'Xander')
Formatting just needs to be changed a little. You were pretty close.
foo = 'John Smith'
cursor.execute("SELECT idx FROM db WHERE name = %s", (foo,))
Take a gander at the links below for more explanation
Python MySQL Parameterized Queries
https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html
According to the docs, you would need to write:
cursor.execute("SELECT idx FROM db WHERE name = %s", ('John Smith'))
In other words, the parameter-replacement values must be contained in an iterable.
(But see the answer from theClap who correctly adds a semi-colon to force "tupleness" where required).

Python and MySQL STR_TO_DATE

When I execute the code (see below) I got the next error
Traceback (most recent call last):
File "/home/test/python/main.py", line 18, in <module>
calls = tel.getCallRecordings(member['id'], member['start_date'])
File "/home/test/python/teldb.py", line 49, in getCallRecordings
'start_date': str(start_date),
File "/usr/local/lib/python2.5/site-packages/MySQL_python-1.2.3-py2.5-freebsd-8.1-RELEASE-amd64.egg/MySQLdb/cursors.py", line 159, in execute
TypeError: int argument required
The code I use is the next:
def getCallRecordings(self, member_id, start_date):
self.cursor.execute("""
SELECT var10 as filename,
var9 as duration
FROM csv_data c
LEFT JOIN transcriptions t ON
c.id=t.call_id
WHERE member_id=%(member_id)s AND
var10 IS NOT NULL AND
var9>%(min_duration)d AND
dialed_date>STR_TO_DATE(%(start_date)s, '%%Y-%%m-%%d %%H:%%i:%%s') AND
t.call_id IS NULL
ORDER BY dialed_date DESC
""", {
'member_id': member_id,
'min_duration': MIN_DURATION,
'start_date': str(start_date),
})
logging.debug("Executed query: %s" % self.cursor._executed)
return self.cursor.fetchone()
Why I got this error? Thanks.
You don't show what MIN_DURATION is, but you use %(min_duration)d, so it is required to be an int. Do you have it defined as a string or a float instead?
You don't need to use %d in a SQL query like this, the DB adapter understands the types you pass it, and will properly insert them into the query. Make MIN_DURATION an integer (perhaps with int(MIN_DURATION) in the code you have), and it will work.
BTW: the stack trace focuses you on the str(start_date), but only because that's the last source line in the executable statement that had the error, so it's misleading.
I have faced a similar issue while constructing the sql query strings involving str_to_date function. I have used .format() operator on python strings to parametrize the SQL queries. Here is an example query that would work just fine:
# Takes an input date and returns the manager's name during that period
input_string='"' + "{input_data}".format(input_data=input_data) + '"'
sql_query='''select CONCAT(e.last_name, ",", e.first_name),STR_TO_DATE(from_date,'%Y-%m-%d'),STR_TO_DATE(to_date,'%Y-%m-%d') from dept_manager dm inner join employees e on e.emp_no=dm.emp_no where STR_TO_DATE({input_string},'%Y-%m-%d')>STR_TO_DATE(from_date,'%Y-%m-%d') and STR_TO_DATE({input_string},'%Y-%m-%d')<STR_TO_DATE(to_date,'%Y-%m-%d');'''.format(input_string=input_string)

Categories