How to build SQL Select statement with columns specified by user? - python

I want to select columns by name specified by user, but I want to avoid SQL Injection.
I think something like that isn't a good idea:
column_one = input("Column one")
column_two = input("Column two")
column_three = input("Column three")
sql.execute("Select {}, {}, {} from table;".format(column_one, column_two, column_three))
I can use something like that:
con = sql.connect("example.sqlite3")
select = "select ? from table;"
t = ('id', )
cur = con.cursor()
cur.execute(selec, t)
rows = cur.fetchall()
con.commit()
con.close()
for row in rows:
for cell in row:
print(cell)
What I get is: id id id id id id id...

Write a query to return all columns from the table, and then select which ones to return using conditional logic.

Related

how to run update sql query based on select query results using python

I am trying to update a row in an sql table based on results of a select query using python. How to add same so that if results found in select query we should be able to run update query and print as list updated, if not exit saying no result found to update table
cursor = conn.cursor()
cursor.execute(
"select * from student where email = 'xyz.com'"
)
student = cursor.fetchall()
print(student)
for row in student:
cursor.execute(" Update student set value = 0 where email = 'xyz.com'")
`
You don't need to do a separate SELECT, you can just use an OUTPUT clause to have your UPDATE statement return the value(s) from the row(s) that are updated. For example, with pyodbc:
sql = """\
UPDATE student SET value = 0
OUTPUT INSERTED.student_number
WHERE email = 'xyz.com' AND (value <> 0 OR value IS NULL)
"""
student_numbers = crsr.execute(sql).fetchall()
print(student_numbers) # [(1001, ), (1003, )]

How can I handle errors inside of a for loop inside of a cx_Oracle connection?

here's a run down of what I'd like to do: I have a list of table names, and I want to run sql against an oracle database and pull back the table name and row count for every table in my table list. However, not every table name in my list of table names is necessarily actually in the database. This causes my code to throw a database error. What I would like to do, is whenever I come to a table name that is not in the database, I create a dataframe that contains the table name and instead of count(*), there's some text that says 'table not found', or something similar. At the end of the loop I'm concatenating all of the dataframes into one dataframe. The overall goal here is to validate that certain tables exist and that they have the expected row counts.
query_list=[]
df_List=[]
connstr= '%s/%s#%s' %(username, password, server)
conn = cx_Oracle.connect(connstr)
with conn:
query_list = ["SELECT '%s' as tbl, count(*) FROM %s." %(elm, database) +elm for elm in table_list]
df_List = [pd.read_sql(elm,conn) for elm in query_list]
df = pd.concat(df_List)
Consider try/except handling to return query output or table not found output:
def get_table_count(sql, conn, elm):
try:
return pd.read_sql(sql, conn)
except:
return pd.DataFrame({'tbl': elm, 'note': 'table not found'}, index = [0])
with conn:
sql = "SELECT '{t}' as tbl, count(*) as table_count FROM {d}.{t}"
df_List = [get_table_count(sql.format(t = elm, d = database), conn, elm) \
for elm in table_list]
df = pd.concat(df_List, ignore_index = True)
Get a list of all the Table Names which are in the DB, then create a loop to query each Table to get the row count.
Here is a SQL statement to get a list of all Tables in an Oracle DB:
SQL:
SELECT DISTINCT TABLE_NAME FROM ALL_TAB_COLUMNS ORDER BY TABLE_NAME ASC;
Python (to make list of tables you want row counts for and which exist in the DB):
list(set(tables_that_exist_in_DB) - (set(tables_that_exist_in_DB) - set(list_of_tables_you_want)))

print the most common value from sql

I have a list of words in an SQLite database and I want to get the most common value and save it in a variable.I am using python3
here is how I got my most common value.
SELECT emotion,
COUNT(emotion) AS value_occurrence
FROM chatlog
GROUP BY emotion
ORDER BY value_occurrence DESC
LIMIT 1;
May be something like this?
#!/usr/bin/python
import sqlite3
conn = sqlite3.connect('yourdb')
cur = conn.cursor()
cur.execute('''SELECT emotion,
COUNT(emotion) AS value_occurrence
FROM chatlog
GROUP BY emotion
ORDER BY value_occurrence DESC
LIMIT 1''')
rows = cur.fetchall()
    for row in rows:
        x = row[0]
y = row[1]
print(x,y)

Python: Set param for columns and values pypyodbc - executemany

I have this situation where I created a method that will insert rows in database. I provide to that method columns, values and table name.
COLUMNS = [['NAME','SURNAME','AGE'],['SURNAME','NAME','AGE']]
VALUES = [['John','Doe',56],['Doe','John',56]]
TABLE = 'people'
This is how I would like to pass but it doesn't work:
db = DB_CONN.MSSQL() #method for connecting to MS SQL or ORACLE etc.
cursor = db.cursor()
sql = "insert into %s (?) VALUES(?)" % TABLE
cursor.executemany([sql,[COLUMNS[0],VALUES[0]],[COLUMNS[1],VALUES[1]]])
db.commit()
This is how it will pass query but problem is that I must have predefined column names and that's not good because what if the other list has different column sort? Than the name will be in surname and surname in name.
db = DB_CONN.MSSQL() #method for connecting to MS SQL or ORACLE etc.
cursor = db.cursor()
sql = 'insert into %s (NAME,SURNAME,AGE) VALUES (?,?,?)'
cursor.executemany(sql,[['John','Doe',56],['Doe','John',56]])
db.commit()
I hope I explained it clearly enough.
Ps. COLUMNS and VALUES are extracted from json dictionary
[{'NAME':'John','SURNAME':'Doe','AGE':56...},{'SURNAME':'Doe','NAME':'John','AGE':77...}]
if that helps.
SOLUTION:
class INSERT(object):
def __init__(self):
self.BASE_COL = ''
def call(self):
GATHER_DATA = [{'NAME':'John','SURNAME':'Doe','AGE':56},{'SURNAME':'Doe','NAME':'John','AGE':77}]
self.BASE_COL = ''
TABLE = 'person'
#check dictionary keys
for DATA_EVAL in GATHER_DATA:
if self.BASE_COL == '': self.BASE_COL = DATA_EVAL.keys()
else:
if self.BASE_COL != DATA_EVAL.keys():
print ("columns in DATA_EVAL.keys() have different columns")
#send mail or insert to log or remove dict from list
exit(403)
#if everything goes well make an insert
columns = ','.join(self.BASE_COL)
sql = 'insert into %s (%s) VALUES (?,?,?)' % (TABLE, columns)
db = DB_CONN.MSSQL()
cursor = db.cursor()
cursor.executemany(sql, [DATA_EVAL.values() for DATA_EVAL in GATHER_DATA])
db.commit()
if __name__ == "__main__":
ins = INSERT()
ins.call()
You could take advantage of the non-random nature of key-value pair listing for python dictionaries.
You should check that all items in the json array of records have the same fields, otherwise you'll run into an exception in your query.
columns = ','.join(records[0].keys())
sql = 'insert into %s (%s) VALUES (?,?,?)' % (TABLE, columns)
cursor.executemany(sql,[record.values() for record in records])
References:
https://stackoverflow.com/a/835430/5189811

How would I clear all data in a selected column in a created SQL database?

I've created a database using my sql/python programming knowledge. However, I wanted to know how I would be able to clear all data in a given column.
The code I tried to use is below:
#Creating the Table
import sqlite3 as lite
import sys
con = lite.connect('Test.db')
with con:
cur = con.cursor()
cur.execute('SELECT SQLITE_VERSION()')
data = cur.fetchone()
print("SQLite version: %s" % data)
#Adding data
with con:
cur = con.cursor()
cur.execute("CREATE TABLE Users(User_Id INTEGER PRIMARY KEY, Username STRING, Password STRING, Acc_Type STRING, First_Name STRING, Surname STRING, Class STRING, FullName STRING)")
cur.execute("INSERT INTO Users VALUES(1, 'Admin', 'PassWord567', 'Admin', '', 'Admin', 'None', 'Admin')")
cur.execute("INSERT INTO Users VALUES(2, 'HamzahA12', 'password', 'Student', 'Hamzah', 'Akhtar', '13E2', 'Hamzah Akhtar')")
#Clearing a Column
column_length = []
with con:
cur = con.cursor()
cur.execute("SELECT Username FROM Users")
rows = cur.fetchall()
for row in rows:
row = str(row)
column_length.append(row)
length = 1
for item in column_length:
length = str(length)
with con:
cur = con.cursor()
cur.execute("DELETE FROM Users WHERE User_Id = '"+length+"'")
length = int(length)
length = length+1
When i run the code, it clears the table rather than the column. I understand why it does that but i cant find a way around it?!
You don't need the two loops; you can change all column values with a single statement:
con.cursor().execute("UPDATE Users SET Username = NULL")
You need to change the line:
cur.execute("UPDATE Users SET YourColumn=null WHERE User_Id = '"+length+"'")

Categories