SQL variable missing quotations - python

I am working with a database and in column_x some variables were NULL. As someone did not prefer this we decided to change this to 'None'. Now I used the following command to change that in Python:
query = "update stone set results = 'None' where results is null;"
But when I do:
query = "SELECT * FROM stone where part = 'ABC';"
I get an output 'x','y','z',None,'a'
But when I do:
query = "SELECT * FROM stone where part = 'ABC' and results = 'None';"
I get () returned. This is probably because 'None' does not exists. Thus short question long, how do I change None -> 'None' via Python?

I wasn't sure if when you said None you meant null.
If you intended None to mean null you can use something like this (MYSQL):
sql = "UPDATE stone set results=\'None\' where results is null"
cursor = conn.Execute($sql)
rows = cursor.Affected_Rows()
For Oracle, execute this SQL:
sql = "UPDATE stone set results=''None'' where results='None'"
cursor = conn.Execute($sql)
rows = cursor.Affected_Rows()
For MYSQL, you need to use a backslash to escape the tick - something like
sql = "UPDATE stone set results=\'None\' where results='None'"
cursor = conn.Execute($sql)
rows = cursor.Affected_Rows()
See also
http://phplens.com/lens/adodb/adodb-py-docs.htm
http://www.codersrevolution.com/index.cfm/2008/7/13/Just-when-you-felt-safe-SQL-Injection-and-MySQL

Related

%s variable in Query Execution Python 3.8 (pymssql)

I have a python script with a basic GUI that logs into a DB and executes a query.
The Python script also asks for 1 parameter called "collection Name" which is taken from the tkinter .get function and is added as a %s inside the Query text. The result is that each time I can execute a query with a different "Collection name". This works and it is fine
Now, I want to add a larger string of Collection Names into my .get function so I can do cursor.execute a query with multiple collection names to get more complex data. But I am having issues with inputing multiple "collection names" into my app.
Below is a piece of my Query1, which has the %s variable that it then gets from the input to tkinter.
From #Session1
Join vGSMRxLevRxQual On(#Session1.SessionId = vGSMRxLevRxQual.SessionId)
Where vGSMRxLevRxQual.RxLevSub<0 and vGSMRxLevRxQual.RxLevSub>-190
and #Session1.CollectionName in (%s)
Group by
#Session1.Operator
Order by #Session1.Operator ASC
IF OBJECT_ID('tempdb..#SelectedSession1') IS NOT NULL DROP TABLE #SelectedSession1
IF OBJECT_ID('tempdb..#Session1') IS NOT NULL DROP TABLE #Session1
Here, is where I try to execute the query
if Query == "GSMUERxLevelSub" :
result = cursor.execute(GSMUERxLevelSub, (CollectionName,))
output = cursor.fetchmany
df = DataFrame(cursor.fetchall())
filename = "2021_H1 WEEK CDF GRAPHS().xlsx"
df1 = DataFrame.transpose(df, copy=False)
Lastly, here is where I get the value for the Collection name:
CollectionName = f_CollectionName.get()
enter image description here
enter code here
Your issues are due to a list/collection being a invalid parameter.
You'll need to transform collectionName
collection_name: list[str] = ['collection1', 'collection2']
new_collection_name = ','.join(f'"{c}"' for c in collection_name)
cursor.execute(sql, (new_collection_name,))
Not sure if this approach will be susceptible to SQL injection if that's a concern.
Edit:
Forgot the DBAPI would put another set of quotes around the parameters. If you can do something like:
CollectionName = ["foo", "bar"]
sql = f"""
From #Session1
Join vGSMRxLevRxQual On(#Session1.SessionId = vGSMRxLevRxQual.SessionId)
Where vGSMRxLevRxQual.RxLevSub<0 and vGSMRxLevRxQual.RxLevSub>-190
and #Session1.CollectionName in ({",".join(["%s"] * len(CollectionName))})
"""
sql += """
Group by
#Session1.Operator
Order by #Session1.Operator ASC
"""
cursor.execute(sql, (CollectionName,))
EDIT: Update to F-string

Get values by using fetchone and verify when the value is null

I'm new to Python and was working on a script which executes a postgres query and pulls its result, it's just a number:
con = psycopg2.connect("dbname=mydb user=postgres host=192.168.0.10")
cur = con.cursor()
myvar='TEST'
cur.execute("SELECT get_id('myvar')")
my_id = cur.fetchone()
print(my_id)
The results I get are like these depending on the myvar value:
(144,)
(140,)
(141,)
Sometimes when there's no value returned by the query, I get this:
(None,)
I was expecting something like "null" (similar to what I get when I run this on the DB) but that wasn't the case.
Question number one is: why do I get the values surrounded by a parenthesis and the comma at the end?
Question two is: How "if" may work when the value is 'None'?
I've tried this:
if my_id=='None':
if my_id=='(None,)':
but didn't work..
The result is a tuple, which is an immutable sequence
Check if the first item of the tuple is None:
if my_id[0] is None:
pass
Also, please be sure that you are using the proper string substitution with psycopg2. Your code should look something like this:
con = psycopg2.connect("dbname=mydb user=postgres host=192.168.0.10")
cur = con.cursor()
myvar='TEST'
cur.execute("SELECT get_id(%s)", [myvar])
my_id = cur.fetchone()[0]
if my_id is not None:
print(my_id)

Django raw SQL in optimization?

I think my code is not very pythonic ,How to optimize?
code
lamp_keys=["ids"]
if len(lamp_keys) == 1:
rsql = f"""
SELECT * from brelation
where source_key = '{lamp_keys[0]}' and target_concept='aaa'
"""
else:
rsql = f"""
SELECT * from brelation
where source_key in {tuple(lamp_keys)} and target_concept='aa'
"""
robjs = RelationModel.objects.raw(rsql)
if lame_keys length is 1, if use in must be error, for example:
SELECT * from `brelation` WHERE source_key in ('xx',) and target_concept='aa'
You make the very dangerous mistake of formatting raw SQL yourself. Suppose in the part:
where source_key = '{lamp_keys[0]}'
Some user decides they want to be malicious and gives some value like '; DROP TABLE brelation; -- for lamp_keys[0] you can imagine what might happen yes? Your table will get dropped! This is called SQL Injection.
When you want to use some user defined value in a raw query always use parameterized queries. Reference: Passing parameters into raw() [Django docs]:
rsql = f"SELECT * from brelation where source_key in %s and target_concept='aaa'"
robjs = RelationModel.objects.raw(rsql, [lamp_keys])
Moving further it doesn't look like you even need to use raw queries, something like below would be equivalent to your raw query:
robjs = RelationModel.objects.filter(source_key__in=lamp_keys, target_concept='aaa')

psycopg2 Programming Error when using .format()

Im not sure exactly whats happening here but it might have something to do with format in python.
Running this causes an error.
x = '00000201000012EB'
sql = """ SELECT * FROM table WHERE id = {} """.format(x)
conn.execute(sql)
I get an error saying: syntax error near "EB"
however when i run the command like this:
sql = """ SELECT * FROM table WHERE id = '00000201000012EB' """
conn.execute(sql)
It works fine.
Is there something wrong with the way im formatting this sql statement?
Use the variable as an argument to execute():
cur.execute(""" SELECT * FROM my_table WHERE id = %s """, (x,))
If you are determined to use format(), you should add single quotes around the placeholder:
sql = """ SELECT * FROM my_table WHERE id = '{}' """.format(x)
Believe it or not it was fixed by adding more quotes to the string.
this finally worked.
x = '00000201000012EB'
sql = """ SELECT * FROM table WHERE id = {} """.format("'" + x + "'")
Since the sql statement required another set of quotes i just added them to ensure it was treated as its own string.

SQL SELECT from table name supplied by a variable

Whenever I try the code below, I get near "?": syntax error
I tried multiple things including prepping it into a variable
Is this possible in python? Or am I thinking in the wrong direction?
import sqlite3
sqlite_file = 'DATABASE.db'
conn = sqlite3.connect(sqlite_file)
c = conn.cursor()
word = ()
question = int(input("What would you like to see?"))
if question == 1:
word = ("Batchnumbers")
if question == 2:
word = ("Worker IDs")
c.execute('SELECT * FROM ?', (word))
data = c.fetchall()
for x in range(len(data)):
print(data[x])
Query parameters can only be used to supply column values, not table or column names. If you need to supply a table name you will have to use dynamic SQL, e.g.,
c.execute('SELECT * FROM "{}"'.format(word))
Note that this approach is vulnerable to SQL injection issues, so you really should consider mitigating those, e.g., ensuring that word does not contain double-quote characters that would cause errors (or worse).
Indeed use this line of code
word =
c.execute('SELECT * FROM "{}"'.format(word))

Categories

Resources