How to do a SQL query using a string wildcard and LIKE? - mysql

I am new to python and currently learning to use SQL with python. I have the following code:
word = input("Enter a word: ")
query = cursor.execute("SELECT * FROM Dictionary WHERE Expression LIKE '%s%' " % word)
results = cursor.fetchall()
The second line throws an error since I don't think I can use '%s%' like that? How would I change this so as to be able to make this work? I want to be able to return all related entries to the users input. So if the user inputs "rain", then I want the query to return all possible results e.g. "raining", "rainy" etc. Thank you.

You can try
query = cursor.execute(f"SELECT * FROM Dictionary WHERE Expression LIKE '%{word}%' ")

You should use cursor.execute() parameter substitution rather than string formatting, to prevent SQL injection.
Then use CONCAT() to surround the search string with %.
query = cursor.execute("SELECT * FROM Dictionary WHERE Expression LIKE CONCAT('%', %s, '%' "), (word,))

Related

filter string only contains q in mysql

I need help in mysql query, i written this query
select * from post where content REGEXP '^q'
this query is working but it also includes spaces in filter, what i want to do if any content string like "qqqqqq" or "qqqq" or "qqq" or "qq" or "q" for this string only it should have to filter, right now what is happening if i have string like "qqqq qq" then also it is giving me the result, it should not consider that space, can anyone please help me to resolve this issue ?
You can fix your regexp like next:
select * from post where content REGEXP '^q+$';
This regular expression mean the string starts with q and contain only 1 or more q symbols till end of string
Test it on SQLize.online
Try Using this ^q+(?![\s])+$ Regular Expression.
Above RegExp will check for string starting with q and without space.
You don't really need a regex for this. String functions are likely to be more efficient. You can replace all "q"s with empty strings, and ensure that that resulting string is empty:
select * from post where replace(content, 'q', '') = ''
Note that this also allows the empty string. If you want to avoid that, then:
select * from post where content <> '' and replace(content, 'q', '') = ''

mysql query using python 3.6 (string variable is in single quotes)

I am new in python as well as mysql. I am having trouble in populating proper query statement for mysql.
sql = "SELECT * FROM Persons WHERE %s"
cur = db.cursor()
cur.execute(sql,(where,))
where is a string variable which creates a string for WHERE clause; this is the point of question. When I print this variable it give the following result:
Gender = True And IsLate = False
(without any quotes) but when I add this variable to the query to execute it, it adds single quotes around the string.
I used the command
print(cur.statement)
and it prints:
SELECT * FROM Persons WHERE 'Gender = True And IsLate = False'
After supplying parameter, it puts it within single quotes and query returns 0 rows.
I have worked around by concatenating the query statement and variable together and execute the string as query, that worked,
sql = sql + where
cur.execute(sql)
But I know that is not the professional way, as I have searched and found the professional way is to use parameterized query and use variable to store the condition(s) and supplying it at the execution of query.
Looking for advice, am I thinking the right way or otherwise?
The whole point of using parameter substitution in cursor.execute() is that it protects you from SQL injection. Each parameter is treated as a literal value, not substituted into the query and re-interpreted.
If you really want it to be interprted, you need to use string formatting or concatenation, as you discovered. But then you will have to be very careful in validating the input, because the user can supply extra SQL code that you may not have expected, and cause the query to malfunction.
What you should do is build the where string and parameter list dynamically.
where = []
params = []
if gender_supplied:
where.append('gender = %s')
params.append(gender)
if islate_supplied:
where.append*('islate = %s')
params.append(islate)
sql = 'select * from persons'
if where:
query = sql + ' where ' + ' and '.join(where)
else:
query = sql
cur.execute(query, params)

Insert into table SET - rows with special characters skipped

I have this query:
$sql = "
INSERT INTO table SET
name = '$name',
sku = '$number',
description = '$desc'
";
But the rows containing some special characters (in my case this ') are not inserted.. How I can solve?
Thanks in advance.
When you construct your query, you need to escape the data you are inserting.
You need to at least use addslashes() function in PHP, like this:
$sql = "INSERT INTO table SET name = '".addslashes($name)."', sku = '".addslashes($number)."', description = '".addslashes($desc)."'";
However more correct way is to use a different function than addslashes, which would properly handle all characters in the data, not only apostrophes.
I am using my custom 'escape' function like this:
function escape($text)
{
return str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $text);
}
So using this function, you would write:
$sql = "INSERT INTO table SET name = '".escape($name)."', sku = '".escape($number)."', description = '".escape($desc)."'";
You must use parameterised queries instead of manually appending those values. Currently if name, number or description would contain any sql it would get executed.
A lot more detailed answer is in How can I prevent SQL injection in PHP?
Read about escaping characters in mysql. I think it is done with \

Convert standard simplified pattern ( * ? ) to the LIKE pattern ( % _ )

I would like to know if there is a better way than :
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE('p%a_t*er?', '\\', '\\\\'), '%', '\%'), '_', '\_'), '*', '%'), '?', '_')
To transform standard search patterns * and ? to the LIKE equivalents % and _ in MySQL ?
There isn't a shorter method to perform multiple-character replacements directly in MySQL. There are alternatives such as User-Defined-Functions (UDFs), but I'm doubtful that any would be beneficial to your exact purpose.
My suggestion would be to perform the text replacement prior-to querying the database, if acceptable.
In PHP, this could be done with:
$searchQuery = $_GET['q'];
$searchQuery = str_replace(array('*', '?'), array('%', '_'), $searchQuery);
// perform your query as normal
In ASP, you could try:
string searchQuery = Request.QueryString["q"];
searchQuery = searchQuery.Replace("*", "%").Replace("?", "_");
// perform your query as normal
Though, both method aren't super-short, they do make it a little easier to read and also won't add any time to your db-query. Also, doing the replacement prior to the query will allow you to replace before the string is sanitized so you won't need to replace the \ as you do in your existing query - which saves you one replacement!
Instead of like you can use regexp of Mysql like this:
select * from my_table where col_name regexp 'p%a_t*er?';
While using regexp there is no need to do all those replacements to make your string like friendly.

Django: raw SQL queries with a dynamic number of variables

Is it possible to construct raw SQL queries in Django so that they accept a dynamic number of arguments? So for example say that I have the following url structure in my app:
/books/category/history/
/books/category/history/1800s/
For the first query, I'm looking for all books with the keyword 'history', and for the second, I'm looking for all books with the keyword 'history' AND the keyword '1800s'.
I currently have two separate queries for each of these:
keyword1 = 'history'
SELECT appname_book.name AS name FROM appname_book WHERE keyword=%s,[keyword1]
keyword1 = 'history'
keyword2 = '1800s'
SELECT appname_book.name AS name FROM appname_book WHERE keyword=%s AND keyword=%s,[keyword1, keyword2]
Anyone know of a cleaner and more efficient way to do this?
I'm using Django 1.3 and MySQL.
Thanks.
Why dont you use Django QuerySet, like this:
Book.objects.all().filter(keyword__in=['history','1800s']).values('name')
Another possible solution using RAW SQL, coud be:
keywords = []
SQL = 'SELECT appname_book.name AS name FROM appname_book WHERE 1=1 '
SQL += ' '.join(['AND keyword=%s' for _ in params])
Sure, you could do something like this to dynamically generate a raw SQL query
sql = 'SELECT id FROM table WHERE 1 = 1'
params = []
if 'description' in args.keys():
sql += ' AND description LIKE %s'
params.append('%'+args['description']+'%')
if 'is_active' in args.keys():
sql += ' AND is_active LIKE %s'
params.append(args['is_active'])
... you can put as many "ifs" you want to construct the query
with connections['default'].cursor() as cursor:
cursor.execute(sql, params)
This way would still be completely safe against SQL Injections vulnerability