I'm working on a registration site and right now I am trying to make multiple bases at the same time.
I have 2 databases, one called Tables, and the other called Digit.
I want to use the SAME function for both of them, only to manage 2 databases at the same time, differ by the front end choice.
I tried to use %s as a place holder for the table name, while i have a dict at the beginning for the different databases (1: Tables, 2 : Digit)
cursor.execute("SELECT * FROM %s WHERE active = %s AND isFull = %s ORDER BY minLevel" , [bases[DB], 1,0])
This is the code I wrote, I was hoping to switch the databases based on the DB given from the front end of the site.
And.. it didn't work. I'm really stuck here, and I am not sure if this way is even legal...
Thanks a head for you help!
I figured it out!
thanks to another post by the way - thank to cursor.query( 'select * from %s;', ('thistable',) ) throws syntax error 1064: ...near ' 'thistable' ' at
the problem is you cant use %s on "database variables", like column, databases, etc.
the way to work around it is to build the query as a string beforehand and then to use execute in this format :
cursor.execute (q , [variable])
while q is the pre-built query.
and while building the query to add the database wanted
so the code above should look like (i have a pre built dictionary)
q= "SELECT * FROM " + dict[Number] + " WHERE active = %s AND isFull = %s ORDER BY minLevel"
cursor.execute(q , [1,0])
while dict is the name of the dictionary, number is the variable i got from the front end. and active , is Full and minLevel are columns of mine i use.
hope it will help somebody!
Related
I am coding a database manager in Python using SQLite3 and tkinter, and I am attempting to build a query function. Each element in my database has several attributes: 'name', 'path', 'seen', 'quality', 'franchise', 'genre' and 'tags'.
If possible, I want the user to be able to select certain options in the GUI and then create a request to the database, but the problem is that the user should be able to select any or all of those attributes to be filtered out or into the query. For example, one query might be asking for all the objects in the database with the name "Tony", franchise "toy Story", and genre "Action", whereas another query might just want all objects of seen "yes".
I've been having a lot of trouble with this, and though I've been tempted to, I can't hardcode every permutation of parts of the SQL Select statement, and I feel like there's a better way anyways I can't see. I've tried setting a 'default statement':
SELECT * FROM objects WHERE and then adding onto it like genre IS ? and if franchise matters than AND franchise IS ?, but then I run into the problem of I don't know how to format the substitutions dynamically. I'm pretty sure this can be done, so I'd love any help. Thanks!
You're absolutely on the right path. Consider building up a list of WHERE clauses and a parallel list of substitutions. In this example, I'm using strings, but you get the idea:
subs = []
where = []
where.append( "name = ?" )
subs.append( "Tony" )
where.append( "franchise = ?" )
subs.append( "Toy Story" )
sql = "SELECT * FROM movies WHERE " + (" AND ".join(where)) + ";"
query = cursor.execute( sql, subs )
I am creating a Python Flask app that interfaces with an SQL database. One of the things it does is take user input and stores it in a database. My current way of doing it looks something like this
mycursor.execute(f"SELECT * FROM privileges_groups WHERE id = {PrivID}")
This is not a good or correct way of doing this. Not only can certain characters such as ' cause errors, it also leaves me susceptible to SQL injection. Could anyone inform me of a good way of doing this?
To protect against injection attacks you should use placeholders for values.
So change
mycursor.execute(f"SELECT * FROM privileges_groups WHERE id = {PrivID}")
to
mycursor.execute("SELECT * FROM privileges_groups WHERE id = ?", (PrivID,))
Placeholders can only store a value of the given type and not an arbitrary SQL fragment. This will help to guard against strange (and probably invalid) parameter values.
However, you can't use placeholders for table names and column names.
Note: trailing comma is required for one-element tuples only but not necessary for multiple-element tuples. The comma disambiguates a tuple from an expression surrounded by parentheses.
Related: How do parameterized queries help against SQL injection?
So, if you want to avoid a sql injection...you have to have a secure query i.e. you don't want your query to doing something it shouldn't be.
queryRun = "SELECT * FROM privileges_groups WHERE id = %s" % (PrivID)
When you use "%s" this variable as a placeholder, you avoid ambiguity as to what the injection can or cannot cause to the overall system.
then..run the .execute() call:
mycursor.execute(queryRun)
Note: this also can be done in one step having all the changes within the .execute() call but you maybe better off splitting into piece-wise approach.
This isn't 100 % but should help a lot.
What I want is execute the sql
select * from articles where author like "%steven%".
For the sake of safety, i used like this way :
cursor.execute('select * from articles where %s like %s', ('author', '%steven%')
Then the result is just empty, not get a syntax error, but just empty set.
But I am pretty sure there is some thing inside, I can get result use the first sql. Is there anything run with my code ?
You can't set a column name like a parameter where you're doing where %s like %s. To dynamically set the column name you need to do actual string manipulation like:
sql = 'select * from articles where '+ sql_identifier('author') +' like %s'
cursor.execute(sql, ('%steven%',))
Where sql_identifier is your lib's function for making an identifier safe for SQL injection. Something like:
# don't actually use this!
def sql_identifier(s):
return '"%s"' % s.replace('"','')
But with actual testing and knowledge of the DB engine you're using.
The problem here is fact a minor mistake. Thanks to #Asad Saeeduddin, when I try to use print cursor._last_executed to check what has happened. I found that what is in fact executed is
SELECT * FROM articles WHERE 'title' LIKE '%steven%', look the quotation mark around the title, that's the reason why I got empty set.
So always remember the string after formatting will have a quotation around
Using:
Python3
SQLite
TKinter
I am currently trying to create a function to search for a keyword in a database, but as soon as I try to combine it with TKinter, it seems to fail.
Here are the relevant lines:
(I tried it in a lot of different ways, those 3 lines below seem to work with variables, but not with the input from TKinter, so I thought they might actually work, if I edit them a little.
The problem I got is, that I'm not experienced in TKinter and SQLite yet and worked with those 2 for about 3 days yet.
def searcher(column):
#Getting input from user (TKinter)
keyword = tk.Entry(self)
keyword.pack()
#Assigning the input to a variable
kword = keyword.get()
c.execute("SELECT * FROM my_lib WHERE {kappa} LIKE {%goal%}".format(kappa=column, goal=kword))
#c.execute("SELECT * FROM my_lib WHERE "+column+"=?", (kword,))
#c.execute("SELECT * FROM my_lib WHERE {} LIKE '%kword%'".format(column))
I want to check if any of the data CONTAINS the keyword, so basically:
k_word in column_data
and not
column_data == k_word
My question is:
Is there a way to take the user input (by TKinter) and search in the database (SQLite) and check, if any data in the database contains the keyword.
The SQLite docs explain that you can use ? as a placeholder in the query string, which allows you so substitute in a tuple of values. They also advise against ever assembling a full query using variables with Python's string operations (explained below):
c.execute("SELECT * FROM my_lib WHERE ? LIKE ?", (column, '%'+kword+'%'))
You can see above that I concatenated the % with kword, which will get substituted into the second ?. This also is secure, meaning it will protect against SQL Injection attacks if needed.
Docs: https://docs.python.org/2/library/sqlite3.html
Related posts: Escaping chars in Python and sqlite
Try:
kword = "%"+kword+"%"
c.execute("SELECT * FROM my_lib WHERE kappa LIKE '%s'" % kword)
After trying over and over again, I got the actual solution. It seems like I can't just add the '%' to the variable like a string, but rather:
c.execute("SELECT * FROM my_lib WHERE {} LIKE '%{}%'".format(column, kword))
I hope i can be clear about my problem. thank you :)
I'm using impala connection (library: from impala.dbapi import connect).
In order to run a query i'm using the execute command:
cursor.execute(query.value, (year_var, month_var,day_var))
Generally - it works just fine, also with variables. the problem begins when i use a SQL LIKE statement (e.g. like '%seo' - which contain %s in it).
The 1st argument (query.value) is a string:
create table bi_db.search_terms as
select search_query,search_contain,count(*) searches
from (
select search_query,
case when lower(search_query) like '%logo%' then 'logo'
when lower(search_query) like '%google%' then 'google'
when lower(search_query) like '%facebook%' then 'facebook'
when lower(search_query) like '%instagram%' then 'instagram'
when lower(search_query) like '%etsy%' then 'etsy'
when lower(search_query) like '%seo%' then 'seo'
when lower(search_query) like '%social media%' then 'social media'
else 'else' end as search_contain
from traffic_db.traffic_parq a
where year = %s AND month = %s AND day = %s AND controller = 'search' and action in ('gigs','users')
and search_query is not null and search_query<>'' ) t
group by search_query,search_contain
the second argument of the cursor.execute (e.g. (year_var, month_var,day_var)) refer to %s i'm putting on the query i run in order to use dynamic variables.
** The problem is that the python thinks it has 5 arguments instead of only 3. that caused because i have %seo and %social in the LIKE statments **
Anyone encountered this kind of problem? know how to solve it?
Many thanks!
You could escape literal percent signs in the query (e.g. %%seo%%), although it would be cleaner to pass the patterns as parameters to execute() as well:
sql = """
create table bi_db.search_terms as
select search_query,search_contain,count(*) searches
from (
select search_query,
case when lower(search_query) like %s then 'logo'
...
"""
cursor.execute(sql, ('%logo%', ...))