I am on the following cx_Oracle version
>>> cx_Oracle.version
'5.0.3'
I am getting this exception in executing a query
"expecting None or a string"
The query is being executed this way
cursor.execute("SELECT * FROM APP_STORE WHERE STORE=:STORE %s" %(order_clause),{'STORE':STORE})
What could be the reason? Similar queries executed earlier in the flow work fine but this one does not.
Appreciate some guidance on this.
You are building your cursor incorrectly. Since you pass a dictionary, you much first prepare your query:
cursor.prepare("SELECT * FROM APP_STORE WHERE STORE=:STORE %s" %(order_clause))
Then you execute it and pass None as the first parameter.
results = cursor.execute(None, {'STORE':STORE})
If you wish to change the STORE parameter and run the query again, all you need to do now is modify the dictionary and rerun the execute statement. prepareing it again is not needed.
More information can be found at the Oracle+Python Querying best practices documentation. The information I provided, above, is in the "Bind Variable Patterns" section (no direct link seems to be available)
Related
There are other questions similar to mine but none of them can help me find a solution. I have a query that is
db.session.query(cls).filter_by(id=id).delete()
and I'm trying to print the exact query. I have tried to following
#1
a = db.session.query(cls).filter_by(id=id).delete()
print str(a) # gives an error
#2
a = db.session.query(cls).filter_by(id=id).delete()
print (a.statement.compile(dialect=postgresql.dialect())) # gives error like
# AttributeError: 'int' object has no attribute 'statement'
#3
query = db.session.query(cls)
print(str(query.statement.compile(
dialect=postgresql.dialect(),
compile_kwargs={"literal_binds": True})))
# prints SELECT person_data.id, person_loc.name, person.address, person.id from person_table
# doesn't show the id deletion in the query
How can I print the exact query the db session is doing during the delete?
The Query.delete() usage is executed immediately so you won't be able to print the statement. I think the return value is the number of rows deleted so that is why you receive that " int' object has no attribute 'statement'". So you can't print that directly other than just using echo flag.
If you are using SQLAlchemy 1.4+ in 2.0 style you can use the delete core construct like q = delete(cls).where(cls.id == id) to generate the statement and then print that. You would actually run it with db.session.execute(q) from that example. There are a lot of caveats to printing bound params (like id).
The caveats are explained in how-do-i-render-sql-expressions-as-strings-possibly-with-bound-parameters-inlined
You could also use the echo flag to print all statements to the logs but that doesn't inline the parameters.
There is a similar question from a long time ago that now has a link to the sqlalchemy doc which I included above. This question involves printing the special orm query delete() method though.
SQLAlchemy: print the actual query
I'm using Python to talk to a Postgres DBMS using psycopg2.
Is it safe to assume that if an INSERT returns without raising an exception, then that INSERT actually did store something new in the database?
Right now, I've been checking the 'rowcount' attribute of the database cursor, and if it's 0 then that means the INSERT failed. However, I'm starting to think that this isn't necessary.
Is it safe to assume that if an INSERT returns without raising an
exception, then that INSERT actually did store something new in the
database?
No.
The affected record count will be zero if:
You ran an INSERT INTO ... SELECT ..., and the query returned no rows
You ran an INSERT INTO ... ON CONFLICT DO NOTHING, and it encountered a conflict
You have a BEFORE INSERT trigger on your table, and the trigger function returned NULL
You have a rule defined which results in no records being affected (e.g. ... DO INSTEAD NOTHING)
(... and possibly more, though nothing comes to mind.)
The common thread is that it will only affect zero records if you told it to, one way or another. Whether you want to treat any of these as a "failure" is highly dependent on your application logic.
Anything which is unequivocally a "failure" (constraint violation, serialisation failure, out of disk space...) should throw an error, so checking the record count is generally unnecessary.
By default postgres will return None for a successful insert:
cursor.execute - The method returns None. If a query was executed, the returned values can be retrieved using fetch*() methods.
http://initd.org/psycopg/docs/cursor.html
If you want to know something about the insert, an easy/efficient option is to use RETURNING (which takes the same options as a SELECT):
INSERT INTO ... RETURNING id
found similar question here, How to check if value is inserted successfully or not?
they seem to use the row count method to check if the data was inserted correctly.
In Python I use mysql connector to do queries, with seperate parameters like:
cursor.execute("update tableA set a=%s,b=%s,c=%s", [1,2,3])
I know that when a query succeeded I can use:
print(cursor.statement)
but how can I get the actual query including parameters if I get an error?
So I would like to get:
"update tableA set a=1,b=2,c=3"
You know that a query succeeded (at least technically - whether the result is what you expected is another problem) because it didn't raise any exception. So the obvious answer is: catch the exception and print your params from there:
myquery = "..."
try:
cursor.execute("myquery", params)
except MySQLdb.MySQLError as e:
# using the logging package would be better
print("query '{}' with params {} failed with {}".format(myquery, params, e))
# let the error propagate if you don't
# know how to / cannot handle it at this point
raise
EDIT : if you want to get the exact query that was executed, then there's nothing that's officially specified by the db api specs. For MySQLdb, there's an undocumented yet public Connection.literal(args) method that you can use with your query and params, ie:
sql = myquery % yourdbconnection.literal(params)
print("query '{}' failed with {}".format(sql, e))
FWIW that's exactly how the executed query is built (cf the source for MySQLdb.cursor.execute()). Now while public (not prefixed with _) it's still undocumented so there's no garanty it will still work that way in the next release - and of course it's implementation specific so it might not work with any other db-api connector.
I use the psycopg2 library for PostgreSQL in python for my production environment but I want to test my code with the sqlite3 library. The problem is that psycopg2 uses %s as a placeholder for parameter substitution, whereas sqlite3 uses ?.
I am not happy with the code I got now, it looks like this:
queries = {
'is_admin': "SELECT * FROM admins WHERE user_id = ?;",
}
if dbtype == 'postgres':
for key, value in queries.items():
queries[key] = value.replace('?', '%s')
It's kind of an ugly hack but I don't want to write all my queries two times, so what's the best solution for this problem?
Using simple ? to %s string replacement is dangerous, you may break your query, or harm the actual data in all sorts of unpredictable ways which could be difficult to debug.
Look into the "SQL for humans" records package that provides a uniform parameterization style for all the supported databases.
Note that records achieves the database-agnostic parameterization style only because of using the text() function from the SQLAlchemy package. You may as well use it directly:
The advantages text() provides over a plain string are backend-neutral
support for bind parameters, per-statement execution options, as well
as bind parameter and result-column typing behavior, allowing
SQLAlchemy type constructs to play a role when executing a statement
that is specified literally.
I am running a query based off of other ids for the query. The problem i have is that sometimes the query won't find a result. Instead of having the entire program crash, how can I check to see if the result will be None?
This is the query I have:
sub_report_id = DBSession.query(TSubReport.ixSubReport).filter(and_(TSubReport.ixSection==sectionID[0], TSubReport.ixReport== reportID[0])).one()
When the code gets executed and no results are found, I get a NoResultFound exception
NoResultFound: No row was found for one()
is there a way to just skip the query if there is not going to be a result?
Found the solution on SO(couldn't find it before)
Getting first row from sqlalchemy
Use first() function instead of one(). It will return None if there is no results.
sub_report_id = DBSession.query(TSubReport.ixSubReport).filter(and_(TSubReport.ixSection==sectionID[0], TSubReport.ixReport== reportID[0])).first()
see documentation here
You can also use one_or_none(), this returns None when there's no result found and is syntactically clearer than first(). No error handling required.
ref: one_or_none()
How would SQLAlchemy know there wasn't going to be a result without doing the query?
You should catch the exception and handle it then:
from sqlalchemy.orm.exc import NoResultFound
try:
sub_report_id = DBSession.query(TSubReport.ixSubReport).filter(and_(TSubReport.ixSection==sectionID[0], TSubReport.ixReport== reportID[0])).one()
except NoResultFound:
sub_report_id = [] # or however you need to handle it