inputting a variable into select when using python and sqlite - python

I have an sqlite db called clients.db with a table called prices. Within the table I have columns ['date', 'xyz', 'abc', 'sta, 'vert']. I am accessing the database from python 3.
I can get a specific number easily enough using:
conn = sqlite3.connect('clients.db')
c = conn.cursor()
c.execute('''SELECT "xyz" FROM prices WHERE date=?''', ('2019-01-07', ))
conn.close()
print(c.fetchone()[0])
This returns 1902 as expected.
However when I try the below, instead of the expected number I get xyz.
conn = sqlite3.connect('clients.db')
c = conn.cursor()
c.execute('''SELECT ? FROM prices WHERE date=?''', ('xyz', '2019-01-07', ))
conn.close()
print(c.fetchone()[0])
and when I add a =? I get sqlite3.OperationalError: near "=": syntax error:
conn = sqlite3.connect('clients.db')
c = conn.cursor()
c.execute('''SELECT =? FROM prices WHERE date=?''', ('xyz', '2019-01-07', ))
conn.close()
print(c.fetchone()[0])

From Python documentation:
Instead, use the DB-API’s parameter substitution. Put ? as a
placeholder wherever you want to use a value, and then provide a tuple
of values as the second argument to the cursor’s execute() method.
You need to use ? placeholder for values but for column names you can use string formatting.
I have created a class, inserted some dummy rows and run a select query which is mentioned in the question.
import sqlite3
class Database(object):
def __init__(self):
self.conn = sqlite3.connect('clients.db')
self.c = self.conn.cursor()
def create_table(self):
try:
self.c.execute('''CREATE TABLE prices (date text, xyz text, abc text, sta text, vert text)''')
except:
pass
def insert_dummy_rows(self):
values = [('2019-01-07', 'xyz1', 'abc1', 'sta1', 'vert1'),
('2019-01-07', 'xyz2', 'abc2', 'sta2', 'vert2'),
('2019-01-08', 'xyz3', 'abc3', 'sta3', 'vert3'),
]
self.c.executemany('INSERT INTO prices VALUES (?,?,?,?,?)', values)
self.conn.commit()
def close_connection(self):
self.conn.close()
def get_single_row(self):
t = ('2019-01-07',)
query = "SELECT {} FROM prices WHERE date=?".format('xyz')
self.c.execute(query, t)
return self.c.fetchone()[0]
if __name__ == '__main__':
db = Database()
db.create_table()
db.insert_dummy_rows()
print(db.get_single_row())
Output:
xyz1

Related

Is there a way using SQLite and Python to write an insert statement with the columns as parameters?

I am trying to clean raw json data by parsing and inserting it into a table of an sqlite db.
I have 22 columns in my table and want to find a way of looping through them so I don't need to write 22 loops which insert the data or a single column.
I have simplified the approach I am trying with the following:
import sqlite3
conn = sqlite3.connect('cdata.sqlite')
cur = conn.cursor()
column = 'name'
value = 'test'
cur.execute('''INSERT INTO COMPANY (?)
VALUES (?)''',(column,),(value,))
conn.commit()
conn.close()
This doesn't work at the moment and return the error TypeError: function takes at most 2 arguments (3 given).
Does anyone know if it is possible to write an SQLite insert statement using 2 parameters like this or another way I might be able to iterate through the columns?
Sample as below:
import sqlite3
conn = sqlite3.connect("cdata.sqlite")
cur = conn.cursor()
column = ("name", "age")
table = f"CREATE TABLE IF NOT EXISTS COMPANY ({column[0]} text, {column[1]} text);"
cur.execute(table)
name = "hello"
age = "1"
sql_stmt = f"INSERT INTO COMPANY({column[0]},{column[1]}) VALUES ('{name}', '{age}')"
cur.execute(sql_stmt)
with conn:
cur.execute("SELECT * FROM COMPANY")
print(cur.fetchall())
conn.commit()
conn.close()

how to mock python postgres database

I try to mock my db but when I test it the result is None.
try:
con = psycopg2.connect(
host="yhvh",
database="python_db",
user="postgres",
password="pass",
)
except:
print("Unable to connect database")
# Open a cursor to perform database operation
cur = con.cursor()
def read(con):
"""
Read data in Database
"""
print("Read")
# execute the query
data ="SELECT id, name FROM employees"
cur.execute(
data
)
# fetchall - returns all entries
rows = cur.fetchall()
for r in rows:
print(f"id {r[0]} name {r[1]}")
this is the code for my testing
def test_read(self):
expected = [9, 'aaa']
with patch('psycopg2.connect') as mock_connect:
mock_con_cm = mock_connect.return_value
mock_con = mock_con_cm.__enter__.return_value
mock_cur = mock_con.cursor.return_value
mock_cur.fetchall.return_value = expected
result = db.read(mock_connect)
self.assertEqual(expected, result)
I get an assertionError: [9, 'aaa'] != None
How the result to have a value that would result is equal to expected ?
First you need to return the rows which contains the list of data from read function if not it will return None.
Then use assertListEqual(expected, result) to check the elements in the list.
Your final code will look like this.
def read(con):
"""
Read data in Database
"""
print("Read")
# execute the query
data ="SELECT id, name FROM employees"
cur.execute(
data
)
# fetchall - returns all entries
rows = cur.fetchall()
for r in rows:
print(f"id {r[0]} name {r[1]}")
return rows
And assertion should be,
self.assertListEqual(expected, result)

retrieving data from table based on a value from a python variable

I am writing a function that will retrieve data from sqlite table based on the parameters user provide. This is the function so far
def database_retrieve(db_file, id):
try:
conn = sqlite3.connect(db_file)
with conn:
sql_command = "SELECT * FROM my_table WHERE id = "+id
cur = conn.cursor()
cur.execute(sql_command)
result = cur.fetchall()
return result
except Exception as e:
print(e)
db_file = 'testdb.db'
print(database_retrieve(db_file, 'subject1'))
This gives me the following error
no such column: subject1
None
When I add subject1, which is an entry under the id column in my_table, directly to the sql command like this
sql_command = "SELECT * FROM my_table WHERE id = 'subject1'"
it works fine and prints all the data.
I am new to sqlite3. Please help. Thanks in advance
These are the links I used to come this far
Python sqlite3 string variable in execute
https://www.dummies.com/programming/databases/how-to-retrieve-data-from-specific-rows-in-mysql-databases/
When you do this
sql_command = "SELECT * FROM my_table WHERE id = "+id
The value of sql_command is
"SELECT * FROM my_table WHERE id = subject1"
As you can see, subject1 is not in quotes. sqlite thinks it is a column, that's why you see that error.
Instead, do this
sql_command = "SELECT * FROM my_table WHERE id = ?"
cur.execute(sql_command, [id])
? acts as a placeholder for the variable id.
The official sqlite3 documentation mentions few others methods
https://docs.python.org/2/library/sqlite3.html
The sql_command string being generated should be something like this (Formatted string):
sql_command = "SELECT * FROM my_table WHERE id = %s AND name = %s" % (212212, 'shashank')

Execute SQL for different where clause from Python

I am trying to print SQL result through python code, where I an trying to pass different predicates of the where clause from a for loop. But the code only taking the last value from the loop and giving the result.
In the below example I have two distinct id values 'aaa' and 'bbb'. There are 4 records for id value = 'aaa' and 2 records for the id value = 'bbb'.
But the below code only giving me the result for the id value ='bbb' not for id value 'aaa'
Can anyone help to identify what exactly wrong I am doing?
import pymysql
db = pymysql.connect(host="localhost", user="user1", passwd="pass1", db="db1")
cur = db.cursor()
in_lst=['aaa', 'bbb']
for i in in_lst:
Sql = "SELECT id, val, typ FROM test123 Where id='{inpt}'".format(inpt=i)
print(Sql)
cur.execute(Sql)
records = cur.fetchall()
print(records)
db.close()
The result I am getting as below
C:\Python34\python.exe C:/Users/Koushik/PycharmProjects/Test20161204/20170405.py
SELECT id, val, typ FROM test123 Where id='bbb'
(('bbb', 5, '1a'), ('bbb', 17, '1d'))
Process finished with exit code 0
import pymysql
db = pymysql.connect(host="localhost", user="root", passwd="1234", db="sakila")
cur = db.cursor()
in_lst=['1', '2']
for i in in_lst:
Sql = "SELECT * FROM actor Where actor_id='{inpt}'".format(inpt=i)
print(Sql)
cur.execute(Sql)
records = cur.fetchall()
print(records)
db.close()
Indentation is your problem, please update the code according to your needs...
Within your for loop, you're formatting the sql statement to replace "{inpt}" with "aaa". However, before you do anything with that value, you're immediately overwriting it with the "bbb" version.
You would need to either:
Store the results somehow before the next iteration of the loop, then process them outside of the loop.
Process the results within the loop.
Something like the following will give you a list containing both results from the fetchall() calls:
import pymysql
db = pymysql.connect(host="localhost", user="user1", passwd="pass1", db="db1")
cur = db.cursor()
in_lst=['aaa', 'bbb']
records = list()
for i in in_lst:
Sql = "SELECT id, val, typ FROM test123 Where id='{inpt}'".format(inpt=i)
print(Sql)
cur.execute(Sql)
records.append(cur.fetchall())
print(records)
db.close()

How to match values in a column?

I have a file temperature.txt with columns:
city
avghigh
avglow
coldmonth
coldavghigh
coldavglow
warmmonth
warmavghigh
warmavglow
I need to return the names of the cities which have the same average low temperature.
I also have this function:
def run_query(db, q, args=None):
conn = sqlite3.connect(db)
cur = conn.cursor()
if args is None:
cur.execute(q)
else:
cur.execute(q, args)
results = cur.fetchall()
cur.close()
conn.commit()
conn.close()
return results
all I got thus far (If it's correct is)
return run_query(noname.db, ('Select Cities, AvgLow from Table')
In SQL, this can be easily done using a self join on the table to get matching AvgLow for different cities like this:
Select
t.Cities,
t.AvgLow
from Table1 t
INNER JOIN Table1 t1 ON t.AvgLow = t1.AvgLow
and t.Cities <> t1.Cities
ORDER BY t.AvgLow;
SQLite Demo

Categories