Python MySQL query using string comparison in where clause - python

I have a strange issue where I can't get an SQL query with parameter to work with a string comparison in the where clause - I don't get a row back. when i connect to the MySQL db via bash, the query works.
python 3.7.3
mysql-connector-python==8.0.11
mysql 5.7
works (getting my row):
select * from my_table where my_column = 'my_string';
also works (getting my row):
cursor.execute(
"""
select *
from my_table
where my_column = 'my_string'
"""
)
doesn't work (cursor.fetchall() is []):
cursor.execute(
"""
select *
from my_table
where my_column = '%s'
""",
('my_string')
)

Be careful with tuples. I think you need ('my_string',).
FYI I wrote the original comment mentioned by #tscherg in his comment below the question.

Remove the quotes:
cursor.execute(
"""
select *
from my_table
where my_column = %s
""",
('my_string')
)

Related

Python find a string with single quote symbol in postgresql table

I need to look up for a string that contains multiple single quotes from my psql table. My current solution is replacing the single quotes with double single quotes like this:
sql_query = f"""SELECT exists (SELECT 1 FROM {table_name} WHERE my_column = '{my_string.replace("'","''")}' LIMIT 1);"""
cursor = connection.cursor()
cursor.execute(sql_query)
Is there a nicer solution for this kind of formatting ?
I solved this by making the query like this
sql_query = f"""SELECT exists (SELECT 1 FROM {table_name} WHERE my_column = %s LIMIT 1);"""
cursor = connection.cursor()
cursor.execute(sql_query, (mystring,))
In this case it formats mystring in such way that it is not executed as sql query and doesn't cause the problems mentioned in the question

psycopg2 prepared delete statement

I am struggling with generating the delete query where parameters for the query is actually a set of values.
So I need to delete rows where parameters are a pair values for example:
delete from table where col1 = %s and col2 = %s
which can be executed in Python like:
cur = conn.cursor()
cur.execute(query, (col1_value, col2_value))
Now I would like to run a query:
delete from table where (col1, col2) in ( (col1_value1, col2_value1), (col1_value2, col2_value2) );
I can generate the queries and values and execute the exact SQL but I can't quite generate prepared statement.
I tried:
delete from table where (col1, col2) in %s
and
delete from table where (col1, col2) in (%s)
But when I try to execute:
cur.execute(query, list_of_col_value_tuples)
or
cur.execute(query, tuple_of_col_value_tuples)
I get an exception that indicates that psycopg2 cannot convert arguments to strings.
Is there any way to use psycopg2 to execute a query like this?
You could dynamically add %s placeholders to your query:
cur = con.cursor()
query = "delete from table where (role, username) in (%s)"
options = [('admin', 'foo'), ('user', 'bar')]
placeholders = '%s,' * len(options)
query = query % placeholders[:-1] # remove last comma
print(query)
print(cur.mogrify(query, options).decode('utf-8'))
Out:
delete from table where (role, user) in (%s,%s)
delete from table where (role, user) in (('admin', 'foo'),('user', 'bar'))
Alternatively, build the query using psycopg2.sql as answered there.
Actually the resolution is quite easy if carefully constructed.
In the miscellaneous goodies of psycopg2 there is a function execute_values.
While all the examples that are given by psycopg2 deal with inserts as the function basically converts the list of arguments into a VALUES list if the call to delete is formatted like so:
qry = "delete from table where (col1, col2) in (%s)"
The call:
execute_values(cur=cur, qry=qry, argslist=<list of value tuples>)
will make the delete perform exactly as required.

how to using MySQL pattern matching and binding parameters in sql query in python?

I know how to use MySQL pattern matching, for example:
SELECT * FROM table WHERE col LIKE '%mid%'
I also know how to bind parameters into a sql query in python, for example:
import MySQLdb
s = 'something'
db = MySQLdb.connect(host=blablabla...)
cur = db.cursor()
sql = "SELECT * FROM table WHERE col = %s"
cur.execute(sql, s)
data = cur.fetchall()
db.close()
But I can't find a method to combine these together in one query, like
sql = "SELECT * FROM table WHERE col LIKE '%%s%'"
cur.execute(sql, s)
where the first and the third '%' are pattern character and the middle '%s' is used to bind parameter s.
Anyone have an idea?
Alright, I will answer myself..
#dsgdfg inspired me and here is my code:
sql = "SELECT * FROM table WHERE col LIKE %s"
cur.execute(sql, "%"+s+"%")
sql = "SELECT * FROM table WHERE col LIKE CONCAT('%', %s, '%')"
cur.execute(sql, s)
(I am assuming that execute deals with escaping, thereby preventing SQL injection.)
for the people using py charm
you can do this
qq=input("enter the author name:")
print(pd.read_sql_query("select Book_Id,Book_Name,book_author from bookd where book_author like '%s'" %("%"+qq+"%",), conn2))

Passing Array Parameter to SQL command

In Python 2.7, I can do this pass a parameter to an sql command like this:
cursor.execute("select * from my_table where id = %s", [2])
I can not get the array equivalent working like this:
cursor.execute("select * from my_table where id in %s", [[10,2]])
Obviously, I can just do string formatting, but I would like to do a proper parameter if possible. I'm using a postgresql database if that matters.
cursor.execute("select * from my_table where id = ANY(%s);", [[10, 20]])
See note. To use IN see section below.
cursor.execute(cursor.mogrify("select * from my_table where id in %s",
[tuple([10, 20])]))

python psycopg2 conditional insert statements

I need to write an INSERT statement that first checks to see if the data already exists. The current code is inside python using psycopg2 to connect to a postgresql db:
sql = """IF NOT EXISTS (SELECT * FROM table \
WHERE col_1 = (%s) AND col_2 = (%s) ) \
INSERT INTO table (col1, col2) \
VALUES (%s, %s);"""
data = ( col1_data, col2_data, col1_data, col2_data)
try:
CURSOR.execute(sql, data)
DB.commit()
except:
print "Cursor failed INSERT INTO table.\n"
which does not work (and I haven't done quality error handling so I don't get any good information).
So, I went into psql and tried just:
IF NOT EXISTS (SELECT * FROM t WHERE c1=d1 AND c2=d2)
INSERT INTO t (c1, c2) VALUES (d1,d2);
and I got the following error:
ERROR: syntax error at or near "IF"
LINE 1: IF NOT EXISTS (SELECT * FROM table WHERE c1 = d1...
^
So I BELIEVE my error is in the sql not the python (though I could be wrong) since this works:
sql = """INSERT INTO t2 (col_0, col_1, col_2) \
VALUES (%s, %s, %s);"""
data = (d1, d2, time.time())
try:
CURSOR.execute(sql, data)
DB.commit()
except:
print "Cursor failed to INSERT INTO t2.\n"
For table 1, my CREATE was:
db=> CREATE TABLE table (
col_0 SERIAL PRIMARY KEY,
col_1 varchar(16),
col_2 smallint
);
NOTICE: CREATE TABLE will create implicit sequence "pm_table_ip_id_seq" for serial column "pm_table.ip_id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pm_table_pkey" for table "pm_table"
CREATE TABLE
I am grateful for any help and guidance.
I used plpgsql for such a requirement in my project
insert_function = """
CREATE LANGUAGE plpgsql;
CREATE FUNCTION insert_if_unique (sql_insert TEXT)
RETURNS VOID
LANGUAGE plpgsql
AS $$
BEGIN
EXECUTE sql_insert;
RETURN;
EXCEPTION WHEN unique_violation THEN
RETURN;
-- do nothing
END;
$$;
"""
cursor.execute(insert_function);
You can use something like below to use it:
cursor.execute("insert_if_unique("+sql+")"%data)
The above query is not parameterized. So please be wary of SQL injection if you are getting the input from an external source.
Note: You can use cursor.mogrify() to evade SQL injection attacks.
sql = cursor.mogrify(sql,data)
cursor.execute("insert_if_unique("+sql+")")
Try reversing those. NOT EXISTS condition with a subquery:
INSERT INTO t (c1, c2) VALUES (d1,d2)
WHERE NOT EXISTS (SELECT * FROM t WHERE c1=d1 AND c2=d2)

Categories

Resources