How can I use a single variable to binding in more than one filter in Django SQL?
What I want:
I defined the variable: date
I want to use the same information in the SQL WHERE Clausures: CUR_DATE, ACHIEVED_DATE
def kpiMonitoring(self):
with connections['db'].cursor()as cursor:
import time
date = time.strftime('%Y%m%d')
cursor.execute("""
SELECT * FROM TABLE1
WHERE CUR_DATE = date
AND ACHIEVED_DATE = date
""",[date])
row = dictfetchall(cursor)
cursor.close()
return row
I can do it by this way, but this solution is not scalable:
def kpiMonitoring(self):
with connections['db'].cursor()as cursor:
import time
date = time.strftime('%Y%m%d')
date2 = date
cursor.execute("""
SELECT * FROM TABLE1
WHERE CUR_DATE = %s
AND ACHIEVED_DATE = %s
""",[date, date2])
row = dictfetchall(cursor)
cursor.close()
return row
Is there another way to do it?
You can perform such query with a named parameter:
cursor.execute(
'''SELECT * FROM TABLE1
WHERE CUR_DATE = %(date)s
AND ACHIEVED_DATE = %(date)s''',
{'date': date }
)
another solution is to simply check if the CUR_DATE is the same as the ACHIEVED_DATE and thus use the parameter only once:
cursor.execute(
'''SELECT * FROM TABLE1
WHERE CUR_DATE = %s
AND ACHIEVED_DATE = CUR_DATE''',
[date]
)
but regardless, using raw queries is not a good idea. It often, as you found out yourself, does not scale very well (making use of LEFT OUTER JOINs is usually shorter with the Django ORM), and usually it is less error prone, and less sensitive for database migrations.
Related
I have a doubt about python and sqlite3.
import sqlite3
conna= sqlite3.connect('db_a')
a = conna.cursor()
connb= sqlite3.connect('db_b')
b = conna.cursor()
I don't know how to ask the relational question between banks, can someone instruct me?
I don't want to use DEF, just the SELECT code for a variable to assume
query = """SELECT COL1 FROM TABLE1.DB_A WHERE NOT EXISTS (SELECT COL1 FROM TABLE2.DB_B WHERE COL1.TABLE2.DE_B = COL1.TABLE1.DE_A)"""
cursor.execute(query)
records = cursor.fetchall()
for row in records:
print(row[0])
Can someone help me?
If the tables exist in different databases you need the ATTACH DATABASE statement to use the 2nd database with the connection object that you connect to the 1st database:
import sqlite3
conn = sqlite3.connect('db_a')
cursor = conn.cursor()
attach = "ATTACH DATABASE 'db_b' AS db_b;"
cursor.execute(attach)
query = """
SELECT t1.COL1
FROM TABLE1 AS t1
WHERE NOT EXISTS (
SELECT t2.COL1
FROM db_b.TABLE2 AS t2
WHERE t2.COL1 = t1.COL1
)
"""
cursor.execute(query)
records = cursor.fetchall()
for row in records:
print(row[0])
detach = "DETACH DATABASE db_b;"
cursor.execute(detach)
Also, instead of EXISTS you could use EXCEPT with the difference being that EXCEPT returns only distinct results:
query = """
SELECT COL1 FROM TABLE1
EXCEPT
SELECT COL1 FROM db_b.TABLE2
"""
I'm aware that the best way to prevent sql injection is to write Python queries of this form (or similar):
query = 'SELECT %s %s from TABLE'
fields = ['ID', 'NAME']
cur.execute(query, fields)
The above will work for a single query, but what if we want to do a UNION of 2 SQL commands? I've set this up via sqlite3 for sake of repeatability, though technically I'm using pymysql. Looks as follows:
import sqlite3
conn = sqlite3.connect('dummy.db')
cur = conn.cursor()
query = 'CREATE TABLE DUMMY(ID int AUTO INCREMENT, VALUE varchar(255))'
query2 = 'CREATE TABLE DUMMy2(ID int AUTO INCREMENT, VALUE varchar(255)'
try:
cur.execute(query)
cur.execute(query2)
except:
print('Already made table!')
tnames = ['DUMMY1', 'DUMMY2']
sqlcmds = []
for i in range(0,2):
query = 'SELECT %s FROM {}'.format(tnames[i])
sqlcmds.append(query)
fields = ['VALUE', 'VALUE']
sqlcmd = ' UNION '.join(sqlcmds)
cur.execute(sqlcmd, valid_fields)
When I run this, I get a sqlite Operational Error:
sqlite3.OperationalError: near "%": syntax error
I've validated the query prints as expected with this output:
INSERT INTO DUMMY VALUES(%s) UNION INSERT INTO DUMMY VALUES(%s)
All looks good there. What is the issue with the string substitutions here? I can confirm that running a query with direct string substitution works fine. I've tried it with both selects and inserts.
EDIT: I'm aware there are multiple ways to do this with executemany and a few other. I need to do this with UNION for the purposes I'm using this for because this is a very, very simplified example fo the operational code I'm using
The code below executes few INSERTS at once
import sqlite3
conn = sqlite3.connect('dummy.db')
cur = conn.cursor()
query = 'CREATE TABLE DUMMY(ID int AUTO INCREMENT NOT NULL, VALUE varchar(255))'
try:
cur.execute(query)
except:
print('Already made table!')
valid_fields = [('ya dummy',), ('stupid test example',)]
cur.executemany('INSERT INTO DUMMY (VALUE) VALUES (?)',valid_fields)
I am trying to save this list of string in my database table all at ones but it's giving me this error and I don't understand I am new to this so can you guys please help me
data = ['Unknown', 'Saqlain', 'fahad', 'Unknown']
mycursor = mydb.cursor()
Date_raw = datetime.datetime.now()
Date = str(Date_raw.strftime("%d%A%b"))
mycursor.execute(f"CREATE TABLE march ( {Date} VARCHAR(255))")
sqlfor = f"INSERT INTO march ({Date}) VALUES(%s)"
mycursor.execute(sqlfor, data)
mydb.commit()``
It works like this but it stores all the names in a single column which i don't want I want all the names in different columns. also my data is dynamic so the list will be different every time
mycursor = mydb.cursor()
Date_raw = datetime.datetime.now()
Date = str(Date_raw.strftime("%d%A%b"))
mycursor.execute(f"CREATE TABLE march ( {Date} VARCHAR(255))")
sqlfor = f"INSERT INTO march ({Date}) VALUE(%s %s %s %s)"
mycursor.execute(sqlfor, data)
mydb.commit()
Simply use executemany which passes a sequence of params into execute call:
mycursor.executemany(sqlfor, [(d,) for d in data])
declare #i INT(11);
SET #i=1;
data = ['Unknown', 'Saqlain', 'fahad', 'Unknown']
mycursor = mydb.cursor()
Date_raw = datetime.datetime.now()
Date = str(Date_raw.strftime("%d%A%b"))
mycursor.execute(f"CREATE TABLE march ( {Date} VARCHAR(255))")
sqlfor = f"INSERT INTO march ({Date}) VALUES(%s)"
WHILE((SELECT ELT(#i,data)) IS NOT NULL)
DO
BEGIN
mycursor.execute(sqlfor, (SELECT ELT(#i,data));
SET #i:= #i+ 1;
mydb.commit();
END;
END WHILE;`
SELECT ELT(1,['100','101']) returns '100' .ELT () returns null when the index is out of bounds
I want to use the select now() query result which is executed in Python in another query but I am unable to do so.
My code :
import MySQLdb
db = MySQLdb.connect(host,username,password,databasename)
cursor = db.cursor()
cursor.execute("SELECT NOW()")
dt = cursor.fetchone()
dt = str(dt) #1
cursor2 = db.cursor()
sql2 = "SELECT pid from PRODUCTS where date between DATE_SUB(" + dt + ", INTERVAL 2 HOUR) and " + dt #... query2
cursor2.execute(sql2)
How can I use the date got in #1 in the #query2. It gives me error.
I even used the DATE_FORMAT function to convert it to the same format in which the NOW() function in SQL gives the output. and then tried using it in the SQL query. But still it gives me syntax error.
You can try using %s on that respective dates
sql2 = "SELECT pid from PRODUCTS where date between DATE_SUB(%s, INTERVAL 2 HOUR) and %s"
cursor2.execute(sql2,(dt,dt))
MySQLdb will automagically transform MySQL datetimes into Python native datetime.datetime objects, and Python native datetime.datetime objects into MySQL-correct datetimes, so you don't have any transformation / formatting or whatever to do by yourself. All it takes is to correctly use the db api:
import MySQLdb
db = MySQLdb.connect(host,username,password,databasename)
cursor = db.cursor()
cursor.execute("SELECT NOW()")
dt = cursor.fetchone()[0] # fetchone returns a tuple
print dt # should print a `datetime.datetime` object
# no need for a second cursor here now you have fetched results
# from your previous query
#cursor2 = db.cursor()
# **ALWAYS** use your db connector's placeholders
sql2 = "SELECT pid from PRODUCTS where date between DATE_SUB(%s, INTERVAL 2 HOUR) and %s"
# this way your db connector will take care of proper transformation / formatting / sanitization / escaping etc
cursor.execute(sql2, (dt, dt))
This link could be useful, try it out!:
https://dev.mysql.com/doc/connector-python/en/connector-python-example-cursor-select.html
Here's what it has:
"The task is to select all employees hired in the year 1999 and print their names and hire dates to the console."
import datetime
import mysql.connector
cnx = mysql.connector.connect(user='scott', database='employees')
cursor = cnx.cursor()
query = ("SELECT first_name, last_name, hire_date FROM employees "
"WHERE hire_date BETWEEN %s AND %s")
hire_start = datetime.date(1999, 1, 1)
hire_end = datetime.date(1999, 12, 31)
cursor.execute(query, (hire_start, hire_end))
for (first_name, last_name, hire_date) in cursor:
print("{}, {} was hired on {:%d %b %Y}".format(
last_name, first_name, hire_date))
cursor.close()
cnx.close()
I have a list that contains the name of columns I want to retrieve from a table in the database.
My question is how to make the cursor select columns specified in the list. Do I have to convert nameList to a string variable before include it in the select statement? Thanks
nameList = ['A','B','C','D',...]
with sqlite3.connect(db_fileName) as conn:
cursor = conn.cursor()
cursor.execute("""
select * from table
""")
As long as you can be sure your input is sanitized -- to avoid SQL injection attack -- you can do:
...
qry = "select {} from table;"
qry.format( ','.join(nameList) )
cursor.execute(qry)
If you're on a really old version of Python do instead:
...
qry = "select %s from table;"
qry % ','.join(nameList)
cursor.execute(qry)
nameList = ["'A(pct)'",'B','C','D',...]
with sqlite3.connect(db_fileName) as conn:
cursor = conn.cursor()
cursor.execute("""
select {} from table
""".format(", ".join(nameList)))