I have been trying to run a parameterized query using the client libraries in Python and I have tried both the named parameters and the positional parameters methods in the documentation, but neither of them worked.
Here's the positional parameters method:
And the output:
The code compiles with no error when I remove the last line of code:
I have a different function that does not use a parameterized query and works just fine:
How can I parameterize it with "id"?
I have tried the named parameters and the positional parameters methods described in the documentation but neither of them worked. I'm expecting to get data for the specific id parameter and put it in a data frame.
Try removing squar brackets from table name clause.
change
select * from [ Table_name ]
to this
select * from Table_name
Related
Consider you have the following code:
import pandas as pd
pd.read_sql("SELECT * FROM foo_schema.run_info WHERE id=:param order by run_id desc", s.bind, **{'param':5})
Whereas s.bind is sqlchemy's engine object.
I get the following error:
{TypeError}read_sql() got an unexpected argument 'param'
what is wrong with my function call?
From the docs,
pd.read_sql?
...
params : list, tuple or dict, optional, default: None
What you're doing is unpacking the dictionary, so it is passed as a keyword argument. See Understanding kwargs in Python for more information.
The correct way to pass parameters is:
pd.read_sql(... params={'param':5})
As #Ilja Everilä expertly mentioned, you should wrap your query inside a call to text in order to have the parameter syntax correctly parsed.
from sqlalchemy import text
pd.read_sql(text(query), s.bind, params={'param':5})
I want to pass in parameters to a sql query when using GeoPandas from_postgis functionality with SQLAlchemy.
classmethod GeoDataFrame.from_postgis(sql, con, geom_col='geom', crs=None, index_col=None, coerce_float=True, params=None)
I have looked at a previous similar question and also here which suggests to use SQLAlchemy's textual SQL option. However, this requires access to con.execute which isn't included in the GeoDataFrame from_postgis option.
Could you suggest the best way to pass the parameters to SQL? If not directly in from_postgis, then how best to construct the full SQL string separately and passing it in as the first sql argument to from_postgis.
For textual SQL, you can add parameters by using .bindparams:
query = text("select * from foo where bar = :a").bindparams(a=1)
For queries you construct in SQLAlchemy, bind parameters are automatically included:
foo = Table(...) # you need to define foo
query = select(["*"]).select_from(foo).where(foo.c.bar == 1)
You can also directly pass parameters via the params parameter of from_postgis, if that's more natural:
df.from_postgis(text("select * from foo where bar = :a"), params={"a": 1})
Do not use str.format as the other answer suggests because it's vulnerable to SQL injection.
I want to call a function that I created in my PostgreSQL database. I've looked at the official SQLAlchemy documentation as well as several questions here on SO, but nobody seems to explain how to set up the function in SQLAlchemy.
I did find this question, but am unsure how to compile the function as the answer suggests. Where does that code go? I get errors when I try to put this in both my view and model scripts.
Edit 1 (8/11/2016)
As per the community's requests and requirements, here are all the details I left out:
I have a table called books whose columns are arranged with information regarding the general book (title, author(s), publication date...).
I then have many tables all of the same kind whose columns contain information regarding all the chapters in each book (chapter name, length, short summary...). It is absolutely necessary for each book to have its own table. I have played around with one large table of all the chapters, and found it ill suited to my needs, not too mention extremely unwieldy.
My function that I'm asking about queries the table of books for an individual book's name, and casts the book's name to a regclass. It then queries the regclass object for all its data, returns all the rows as a table like the individual book tables, and exits. Here's the raw code:
CREATE OR REPLACE FUNCTION public.get_book(bookName character varying)
RETURNS TABLE(/*columns of individual book table go here*/)
LANGUAGE plpgsql
AS $function$
declare
_tbl regclass;
begin
for _tbl in
select name::regclass
from books
where name=bookName
loop
return query execute '
select * from ' ||_tbl;
end loop;
end;
$function$
This function has been tested several times in both the command line and pgAdmin. It works as expected.
My intention is to have a view in my Flask app whose route is #app.route('/book/<string:bookName>') and calls the above function before rendering the template. The exact view is as follows:
#app.route('/book/<string:bookName>')
def book(bookName):
chapterList = /*call function here*/
return render_template('book.html', book=bookName, list=chapterList)
This is my question: how do I set up my app in such a way that SQLAlchemy knows about and can call the function I have in my database? I am open to other suggestions of achieving the same result as well.
P.S. I only omitted this information with the intention of keeping my question as abstract as possible, not knowing that the rules of the forum dictate a requirement for a very specific question. Please forgive me my lack of knowledge.
If you want to do it without raw sql, you can use func from sqlalchemy:
from sqlalchemy import func
data = db.session.query(func.your_schema.your_function_name()).all()
You can use func
Syntax:
from sqlalchemy import func
func.function_name(column)
Example:
from sqlalchemy import func
result = db.session.query(func.lower(Student.name)).all()
I found a solution to execute the function with raw SQL:
Create a connection
Call the function as you normally would in the database GUI. E.g. for the function add_apples():
select add_apples();
Execute this statement, which should be a string.
Example code:
transaction = connection.begin()
sql = list() # Allows multiple queries
sql.append('select add_apples();')
print('Printing the queries.')
for i in sql:
print(i)
# Now, we iterate through the sql statements executing them one after another. If there is an exception on one of them, we stop the execution
# of the program.
for i in sql:
# We execute the corresponding command
try:
r = connection.execute(i)
print('Executed ----- %r' % i)
except Exception as e:
print('EXCEPTION!: {}'.format(e))
transaction.rollback()
exit(-1)
transaction.commit()
from sqlalchemy.sql import text
with engine.connect() as con:
statement = text("""your function""")
con.execute(statement)
You must execute raw sql through sqlalchemy
Since from is a special python keyword I am not able to pass it pyes.es.search function. It give syntax error. pyes.es.search(maf, "twitter", "tweet", sort="timestamp", size=2, from=3) . I passed keyword arguments containing from also as below but from did not work while other worked.
keywords = {'sort': 'timestamp', 'size':3, 'from':2}
r = pyes.es.search(maf, "twitter", "reply",**keywords)
This problem also available for another python elasticsearch module here here. In search function interface there is from argument.
Did you try with start parameter?
It sounds like the one to use.
See http://pyes.readthedocs.org/en/latest/references/pyes.queryset.html#pyes.queryset.QuerySet.start
Can I implement the following in SQLAlchemy,
SELECT *
FROM TABLE
WHERE RIGHT(COLUMN_CODE, 2) = 'AX'
here RIGHT( ) returns the right part of a character string with the specified number of characters.
Is there a SQLAlchemy implementation of the RIGHT function?
You'd be better off using the .endswith() method instead:
select([tabledef]).where(tabledef.c.column_code.endswith('AX'))
or, when filtering with a mapper config and a session:
session.query(mappedobject).filter(mappedobject.column_code.endswith('AX'))
The column_code.endswith() method will be translated to whatever SQL is best for your particular engine, matching column values that end with AX.
You can always use the function generator to create arbitrary SQL functions if you have to use the RIGHT() sql function directly:
from sqlalchemy.sql.expression import func
select([tabledef]).where(func.right(tabledef.c.column_code, 2) == 'AX')
and the func.right() call will be translated to RIGHT(column_code, 2) by the SQL generation layer.
The documentation does not make it clear, but you can write any function using func.funcname sytle. funcname does not have to be defined natively by SQLAlchemy module. SQLAlchemy knows about common functions like min, max etc. and if there is dialect to dialect variation amongst those functions, SQLAlchemy takes care of that for you.
But the functions that SQLAlchemy does not know about are passed as is. So you can create your query that generates a SQL statement with the required RIGHT function like so
>>> from sqlalchemy import func
>>> select([table]).where(func.RIGHT(users.c.column_code, 2)='AX')