The read_sql docs say this params argument can be a list, tuple or dict (see docs).

To pass the values in the sql query, there are different syntaxes possible: ?, :1, :name, %s, %(name)s (see PEP249).
But not all of these possibilities are supported by all database drivers, which syntax is supported depends on the driver you are using (psycopg2 in your case I suppose).

In your second case, when using a dict, you are using 'named arguments', and according to the psycopg2 documentation, they support the %(name)s style (and so not the :name I suppose), see http://initd.org/psycopg/docs/usage.html#query-parameters.
So using that style should work:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" '
                     'where "Timestamp" BETWEEN %(dstart)s AND %(dfinish)s'),
                   db,params={"dstart":datetime(2014,6,24,16,0),"dfinish":datetime(2014,6,24,17,0)},
                   index_col=['Timestamp'])
Answer from joris on Stack Overflow
Top answer
1 of 2
134

The read_sql docs say this params argument can be a list, tuple or dict (see docs).

To pass the values in the sql query, there are different syntaxes possible: ?, :1, :name, %s, %(name)s (see PEP249).
But not all of these possibilities are supported by all database drivers, which syntax is supported depends on the driver you are using (psycopg2 in your case I suppose).

In your second case, when using a dict, you are using 'named arguments', and according to the psycopg2 documentation, they support the %(name)s style (and so not the :name I suppose), see http://initd.org/psycopg/docs/usage.html#query-parameters.
So using that style should work:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" '
                     'where "Timestamp" BETWEEN %(dstart)s AND %(dfinish)s'),
                   db,params={"dstart":datetime(2014,6,24,16,0),"dfinish":datetime(2014,6,24,17,0)},
                   index_col=['Timestamp'])
2 of 2
-1

I was having trouble passing a large number of parameters when reading from a SQLite Table. Then it turns out since you pass a string to read_sql, you can just use f-string. Tried the same with MSSQL pyodbc and it works as well.

For SQLite, it would look like this:

# write a sample table into memory
from sqlalchemy import create_engine
df = pd.DataFrame({'Timestamp': pd.date_range('2020-01-17', '2020-04-24', 10), 'Value1': range(10)})
engine = create_engine('sqlite://', echo=False)
df.to_sql('MyTable', engine);

# query the table using a query
tpl = (1, 3, 5, 8, 9)
query = f"""SELECT Timestamp, Value1 FROM MyTable WHERE Value1 IN {tpl}"""
df = pd.read_sql(query, engine)

If the parameters are datetimes, it's a bit more complicated but calling the datetime conversion function of the SQL dialect you're using should do the job.

start, end = '2020-01-01', '2020-04-01'
query = f"""SELECT Timestamp, Value1 FROM MyTable WHERE Timestamp BETWEEN STRFTIME("{start}") AND STRFTIME("{end}")"""
df = pd.read_sql(query, engine)
🌐
Pandas
pandas.pydata.org › docs › reference › api › pandas.read_sql_query.html
pandas.read_sql_query — pandas 3.0.1 documentation
pandas.read_sql_query(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, chunksize=None, dtype=None, dtype_backend=<no_default>)[source]# Read SQL query into a DataFrame. Returns a DataFrame corresponding to the result set of the query string. Optionally provide an ...
Discussions

python - Binding list to params in Pandas read_sql_query with other params - Stack Overflow
I've been trying to test various methods for making my code to run. To begin with, I have this list: member_list = [111,222,333,444,555,...] I tried to pass it into this query: query = pd. More on stackoverflow.com
🌐 stackoverflow.com
How do i use a python variable in a where clause pd.read_sql_query query

Using %s or f-strings opens you up to SQL Injection.

The way to pass parameters I come across most often (see documentation for module sqlite3) is cursor.execute("SELECT * FROM People WHERE Name=?", (my_name, )).

However pandas.read_sql_query docs say that parameters are passed as via the params keyword argument, not as the 2nd positional arg.

More on reddit.com
🌐 r/learnpython
11
1
November 19, 2018
Pandas Parametized Query
From the pandas.read_sql() documentation , it looks like you need the params argument. Probably like this: df1 = pd.read_sql("select * from orders where datecreated > %s and datecreated < %s ", params=(startdate, currentdate), con=db) More on reddit.com
🌐 r/learnpython
2
1
October 25, 2022
read_sql should accept a sql_params parameter
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. ... There was an error while loading. Please reload this page. ... I wonder if current use of read_sql ... More on github.com
🌐 github.com
13
August 24, 2015
🌐
Pandas
pandas.pydata.org › docs › reference › api › pandas.read_sql.html
pandas.read_sql — pandas 3.0.1 documentation - PyData |
>>> pd.read_sql("test_data", "postgres:///db_name") For parameterized query, using params is recommended over string interpolation.
Top answer
1 of 3
27

Break this up into three parts to help isolate the problem and improve readability:

  1. Build the SQL string
  2. Set parameter values
  3. Execute pandas.read_sql_query

Build SQL

First ensure ? placeholders are being set correctly. Use str.format with str.join and len to dynamically fill in ?s based on member_list length. Below examples assume 3 member_list elements.

Example

member_list = (1,2,3)
sql = """select member_id, yearmonth
         from queried_table
         where yearmonth between {0} and {0}
         and member_id in ({1})"""
sql = sql.format('?', ','.join('?' * len(member_list)))
print(sql)

Returns

select member_id, yearmonth
from queried_table
where yearmonth between ? and ?
and member_id in (?,?,?)

Set Parameter Values

Now ensure parameter values are organized into a flat tuple

Example

# generator to flatten values of irregular nested sequences,
# modified from answers http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python
def flatten(l):
    for el in l:
        try:
            yield from flatten(el)
        except TypeError:
            yield el

params = tuple(flatten((201601, 201603, member_list)))
print(params)

Returns

(201601, 201603, 1, 2, 3)

Execute

Finally bring the sql and params values together in the read_sql_query call

query = pd.read_sql_query(sql, db2conn, params)
2 of 3
15

WARNING! Although my proposed solution here works, it is prone to SQL injection attacks. Therefor, it should never be used directly in backend code! It is only safe for offline analysis.

If you're using python 3.6+ you could also use a formatted string litteral for your query (cf https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-pep498)

start, end = 201601, 201603
selected_members = (111, 222, 333, 444, 555)  # requires to be a tuple

query = f"""
    SELECT member_id, yearmonth FROM queried_table
    WHERE yearmonth BETWEEN {start} AND {end}
      AND member_id IN {selected_members}
"""

df = pd.read_sql_query(query, db2conn)
🌐
Like Geeks
likegeeks.com › home › python › pandas › using the pandas read_sql params for dynamic data retrieval
Using the Pandas read_sql params for Dynamic Data Retrieval
December 9, 2023 - query = "SELECT * FROM call_logs WHERE network IN (:networks)" params = handle_params(networks=('Verizon', 'AT&T')) df = pd.read_sql(query, conn, params=params) In this scenario, handle_params would need to be extended to properly format lists into a tuple, as SQLite requires for IN clauses. There are two primary placeholder syntaxes used in SQL queries: %s and :name. The %s syntax is often used with databases like MySQL and PostgreSQL. It represents positional parameters in your query. import pandas as pd import psycopg2 # assuming we're using PostgreSQL conn = psycopg2.connect("dbname=telecom_data user=your_username") query = "SELECT * FROM call_logs WHERE duration > %s AND network = %s" params = [60, 'Verizon'] df = pd.read_sql(query, conn, params=params)
🌐
Plain English
plainenglish.io › home › blog › python › pandas read_sql with variable parameters — alternative way
Pandas Read_Sql With Variable Parameters — Alternative Way
November 26, 2022 - First, we need our SP. In this example, name of my SQL — related things are below. ... In this example, our SP is taking 2 date parameters: StartDate and EndDate. ... Now, we are ready to write our query in Python. We will use an awesome library: Pandas.
🌐
Reddit
reddit.com › r/learnpython › how do i use a python variable in a where clause pd.read_sql_query query
r/learnpython on Reddit: How do i use a python variable in a where clause pd.read_sql_query query
November 19, 2018 -

Hi all,

As per heading I am creating a data frame using SQL that looks something like this:

SQL_Query = pd.read_sql_query(
"""SELECT TOP (1000)
DATA.NAME,
DATA.AGE,
DATA.ADDRESS,
DATA2.COUNTRY
FROM DATA
LEFT JOIN DATA2
ON DATA.NAME=DATA2.NAME
WHERE COUNTRY = (PYTHON VARIABLE )

What is the proper way to do this? I have seen online using %s as below

ursor1.execute("SELECT * FROM People WHERE Name=%s", (myName,))

but this doesn't seem to work. Not sure if it's because I'm using the pd.read_sql_query function.

Any help would be great :)

EDIT: worked it out :)

(Select * from data WHERE data.field = ?),con,Params=[variable])

Thank you all

🌐
Pandas
pandas.pydata.org › pandas-docs › version › 0.19 › generated › pandas.read_sql_query.html
pandas.read_sql_query — pandas 0.19.2 documentation
Comparison with SAS · API Reference ... corresponding to the result set of the query string. Optionally provide an index_col parameter to use one of the columns as the index, otherwise default integer index will be used....
Find elsewhere
🌐
Pandas
pandas.pydata.org › pandas-docs › version › 0.20 › generated › pandas.read_sql_query.html
pandas.read_sql_query — pandas 0.20.3 documentation
Comparison with SAS · API Reference ... corresponding to the result set of the query string. Optionally provide an index_col parameter to use one of the columns as the index, otherwise default integer index will be used....
🌐
Readthedocs
pyhelpers.readthedocs.io › en › latest › _generated › pyhelpers.dbms.PostgreSQL.read_sql_query.html
PostgreSQL.read_sql_query - PyHelpers - Read the Docs
kwargs – [Optional] Additional parameters for the function pandas.read_csv(). ... Data queried by the statement sql_query.
🌐
Reddit
reddit.com › r/learnpython › pandas parametized query
r/learnpython on Reddit: Pandas Parametized Query
October 25, 2022 -

Hello Guys,

I'm trying to query data with variables using the select statement with pandas and MySQL. Is there a way I can declare the date variable and pass them to the query during runtime. I haven't come across any ways that work from my online research.

Here is my code :

from datetime import datetime
from email import encoders
import smtplib
import pandas as pd
from sqlalchemy import create_engine
from urllib.parse import quote  
import mysql.connector as sql

db = create_engine('mysql://root:%s@localhost:3306/store' % quote('Mypass@12!'))

now = datetime.now()
startdate = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0).strftime("%y-%m-%d %H:%M:%S")
currentdate = now.replace(day=3,hour=23, minute=00, second=0).strftime("%y-%m-%d %H:%M:%S")

df1 = pd.read_sql("select * from orders where datecreated > %s and datecreated < %s ", con=db)

pdwriter = pd.ExcelWriter('report.xlsx', engine='xlsxwriter')
df1.to_excel(pdwriter, sheet_name='GEN')
pdwriter.save()

I would like to pass the date variables to the query.

Any suggestion is greatly appreciated. Thank you.

🌐
GitHub
github.com › pandas-dev › pandas › issues › 10899
read_sql should accept a sql_params parameter · Issue #10899 · pandas-dev/pandas
August 24, 2015 - Hello, I wonder if current use of read_sql couldn't lead to SQL injection. I read in https://docs.python.org/2/library/sqlite3.html # Never do this -- insecure! symbol = 'RHAT' c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbo...
Author   s-celles
🌐
Pandas
pandas.pydata.org › docs › dev › reference › api › pandas.read_sql.html
pandas.read_sql — pandas 3.0.0rc0+27.g47fea804d6 documentation
>>> pd.read_sql("test_data", "postgres:///db_name") For parameterized query, using params is recommended over string interpolation.
🌐
Python Forum
python-forum.io › thread-18705.html
Passing parameters to SQL Server using pandas
Hello Python forum, I'm new to python world. Please bear with me if my question sounds silly. My problem statement : Passing parameter to SQL server using pandas. Note: Have imported all the necessary library for pandas,datetime,pyodbc in my cod...
🌐
Apache
spark.apache.org › docs › latest › api › python › reference › pyspark.pandas › api › pyspark.pandas.read_sql_query.html
pyspark.pandas.read_sql_query — PySpark 4.1.1 documentation
Read SQL query into a DataFrame. Returns a DataFrame corresponding to the result set of the query string. Optionally provide an index_col parameter to use one of the columns as the index, otherwise default index will be used.
🌐
Plus2Net
plus2net.com › python › pandas-mysql.php
MySQL table data to Python Pandas DataFrame by read_sql()
February 5, 2019 - print(my_data[['name','class']]) ( Query can be changed to retrieve only required columns ) We can use SQLAlchemy database connection to get data to DataFrame. import pandas as pd from sqlalchemy import create_engine my_conn = create_engine("mysql+mysqldb://usrid:password@localhost/my_db") my_data = pd.read_sql("SELECT * FROM student WHERE class='four'",my_conn) print(my_data) We will use params to pass parameters to our query
🌐
Stack Overflow
stackoverflow.com › questions › 70681722 › error-with-params-in-pandas-read-sql-query › 70682142
python - Error with params in Pandas read_sql_query - Stack Overflow
I have a simple SQl query and i want to use params, but it returns a database error when I add the param. If I change the dynamic param to a fixed value, it works. ... sql = """ SELECT p.description, SUM(p.price) as price FROM product p WHERE p.extenal_id = ? GROUP BY p.description """ result = pd.read_sql_query(sql, con=conn, params=[202101])
🌐
Spark By {Examples}
sparkbyexamples.com › home › pandas › pandas read sql query or table with examples
Pandas Read SQL Query or Table with Examples - Spark By {Examples}
December 2, 2024 - Using parameters helps protect against SQL injection and allows for dynamic queries. Pandas supports parameterized queries through the params argument in both read_sql_query() and read_sql_table() functions.
🌐
Pandas
pandas.pydata.org › pandas-docs › version › 1.1 › reference › api › pandas.read_sql.html
pandas.read_sql — pandas 1.1.5 documentation
pandas.read_sql(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, columns=None, chunksize=None)[source]¶ · Read SQL query or database table into a DataFrame.
🌐
Pandas
pandas.pydata.org › pandas-docs › stable › reference › api › pandas.read_sql.html
pandas.read_sql — pandas 2.2.3 documentation - PyData |
>>> pd.read_sql("test_data", "postgres:///db_name") For parameterized query, using params is recommended over string interpolation.