"Delete from" deletes everything - python

I have a python function that deletes a row in mysql table using name attribute as a condition:
def delete(table: str, name: str):
cursor.execute(f"DELETE FROM {table} WHERE name = {name}")
conn.commit()
I have one row with a name attribute equal to "Name". When I use this function with "Name" it deletes every single row in a table.
I'm guessing that it has to do with passed string being same as attribute. But what would be the solution to that problem except renaming attributes?

So for one, I think you are missing quotes around name, as well as a semicolon.
For further reading you should also take a look at Python parameterized query and Prepared Statement
I do agree with the comments, that table should not be an injected argument for security reasons!
def delete(table: str, name: str):
query = f"DELETE FROM {table} WHERE name = ?"
print(query)
cursor.execute(query, (name,))
conn.commit()`
EDIT FULL WORKING EXAMPLE:
import sqlite3
conn = sqlite3.connect("test")
query_create = '''CREATE TABLE IF NOT EXISTS projects (
id integer PRIMARY KEY,
name text NOT NULL,
begin_date text,
end_date text
);'''
conn.execute(query_create)
query_insert = '''insert into projects (id, name, begin_date, end_date) values (1,"name","date","date")'''
conn.execute(query_insert)
query_select = '''select * from projects'''
cur = conn.execute(query_select)
print(cur.fetchall())
def delete(table: str, name: str):
query = f"DELETE FROM {table} WHERE name = ?"
print(query)
conn.execute(query, (name,))
delete('projects', 'name')
cur = conn.execute(query_select)
print(cur.fetchall())
Gives Output:
[(1, 'name', 'date', 'date')]
DELETE FROM projects WHERE name = ?
[]

Related

Python-sqlite3 : How to put a python variable in SELECT statement

How can I put a python variable just after the SELECT. The idea is to create a python function with three arguments where you can choose what you what (here, it's the age) from whom (here, it's Mike and James)
conn = sqlite3.connect('test.s3db')
cur = conn.cursor()
cur.execute('''DROP TABLE IF EXISTS people''')
cur.execute('''CREATE TABLE IF NOT EXISTS people
(id INTEGER,
name TEXT,
surname TEXT,
age INTEGER,
alone INTEGER DEFAULT 0);''')
def add_people(id, name, surname, age, alone=0):
cur.executemany('INSERT INTO people (id, name, surname, age, alone) VALUES (?,?,?,?,?)', [(id, name, surname, age, alone)])
conn.commit()
add_people(1, 'SMITH','James',45)
add_people(2,'JOHNSON','Mike',75)
cur.execute('''SELECT (?) FROM people WHERE surname = (?) OR surname = (?)''', ('age','Mike', 'James'))
print(cur.fetchall())
My code return:
[('age',), ('age',)]
instead of :
[(75,), (45,)]
EDIT : I want that what is selected is a variable and not directly written in the query. My goal is to make a function like this one :
def query(what, who_1, who_2):
cur.executemany('''SELECT (?) FROM people WHERE surname = (?) OR surname = (?)''', (what, who_1, who_2))
return cur.fetchall()
Thank you in advance for your answers !
This takes the data you need as argument of select_data_of
import sqlite3
def add_people(id, name, surname, age, alone=0):
cur.executemany('INSERT INTO people (id, name, surname, age, alone) VALUES (?,?,?,?,?)', [(id, name, surname, age, alone)])
conn.commit()
def select_data_of(names, data="age"):
select = []
for name in names:
cur.execute(f'''SELECT [{data}] FROM people WHERE surname = (?)''', (name, ))
select.append(cur.fetchall()[0])
return select
with sqlite3.connect('test.s3db') as conn:
cur = conn.cursor()
cur.execute('''DROP TABLE IF EXISTS people''')
cur.execute('''CREATE TABLE IF NOT EXISTS people
(id INTEGER,
name TEXT,
surname TEXT,
age INTEGER,
alone INTEGER DEFAULT 0);''')
add_people(2,'JOHNSON','Mike',75)
add_people(1, 'SMITH','James',45)
data = select_data_of(("Mike", "James"), data="age")
print(data)
OUT:
[(75,), (45,)]
I think your select query is wrong because of the 'ages' parameter, this new query will work.
Try
cur.execute("SELECT [age] FROM people WHERE surname = 'Mike' OR surname = 'James")

how to pass less parameters to a function for sql queries in python

Here is my code. I just want to update of the title of the book and the name of the author and I want other parameter values remain the same. I get an error as below. What should I pass for not changing parameters? I have tried to pass just variable names as year and isbn but it did not work. I searched a lot in similar questions but it did not help.
def update(id, title, author, year, isbn):
conn = psycopg2.connect("dbname='' user= password='' host='localhost' port='5432' ")
cur = conn.cursor()
cur.execute("UPDATE dnr SET title=%s, author=%s, year=%s, isbn=%s WHERE id=%s", (title, author, year, isbn, id))
conn.commit()
conn.close
update(1, "The Sky", "Jonh Smith")
Error:
TypeError: update() missing 2 required positional arguments: 'year' and 'isbn'
You can use default values for optional parameters and check if they are set, adjusting the query and data accordinly.
def update(id, title, author, year=None, isbn=None):
conn = psycopg2.connect("dbname='' user= password='' host='localhost' port='5432' ")
cur = conn.cursor()
query = "UPDATE dnr SET title=%s, author=%s"
data = [title, author]
if year is not None:
query += ", year=%s"
data.append(year)
if isbn is not None:
query += ", isbn=%s"
data.append(isbn)
query += " WHERE id=%s"
data.append(id)
cur.execute(query, data)
conn.commit()
conn.close
update(1, "The Sky", "Jonh Smith")

python sqlite3 query with AND

I am trying to build a simple Address book GUI that has a wx.listbox, that holds all the names in the book, first and last. Once clicked, it will return the information attached to the name from a database file. Right now I have it working by just the last name, I am trying to match first and last names. I am not, really, familiar with the SQLite 3 commands and syntax.
The function is below, this works fine now, but I want to change the query to something like:
select * from AddressBook where Last like names[0] and First like names[1]
Any help would be great!
def onListBox(self, event):
name = event.GetEventObject().GetStringSelection()
names = name.split(',')###names[0]=Last name, names[1] = first name
cursor = db.cursor()
cursor.execute("select * from AddressBook where Last like ?",('%'+names[0]+'%',) )
result = cursor.fetchall()
return result
The query from your comment should work.
Here is a small working example:
import sqlite3
conn = sqlite3.connect("test.sql")
cursor = conn.cursor()
cursor.execute("create table address_book (first_name text, last_name text)")
names = [["John", "Smith"], ["Jane", "Smith"]]
for first_name, last_name in names:
cursor.execute("insert into address_book (first_name, last_name) values (?, ?)", (first_name, last_name))
cursor.execute("select * from address_book where first_name like ? and last_name like ?", ("%" + names[0][0] + "%", "%" + names[0][1] + "%"))
print(cursor.fetchall())
It prints:
[('John', 'Smith')]

(Python) cursor.execute(sql)

def makeProductTable():
"""This creates a database with a blank table."""
with connect("products.db") as db:
cursor = db.cursor()
cursor.execute("""
CREATE TABLE Product(
ProductID integer,
GTIN integer,
Description string,
StockLevel integer,
Primary Key(ProductID));""")
db.commit()
def editStockLevel():
with connect("products.db") as db:
cursor = db.cursor()
Product_ID=input("Please enter the id of the product you would like to change: ")
Stock_Update=input("Please enter the new stock level: ")
sql = "update product set StockLevel = ('Stock_Update') where ProductID = ('Product_ID');"
cursor.execute(sql)
db.commit()
return "Stock Level Updated."
The first function is used to make the table and it shows my column titles, the second function is needed to update a specific value in the table.
But when this is ran the inputs are executed, however when all show all the products in the table the value for stock level doesn't change.
So I think the problem has something to do with the cursor.execute(sql) line.
Or something like this?
cur.execute("UPDATE Product set StockLevel = ? where ProductID = ?",(Stock_Update,Product_ID))
Yes; you're passing literal strings, instead of the values returned from your input calls. You need to use parameters in the statement and pass thme to the execute call.
sql= "update product set StockLevel = %s where ProductID = %s;"
cursor.execute(sql, (Stock_Update, Product_ID))

SQLite: INSERT or REPLACE w/ null PRIMARY KEY

I am trying to INSERT or REPLACE INTO t1 if the name is already there. I understand if the id is set then replace will work, but I need it to react to name.
import sqlite3
def insert(name):
cur.execute('INSERT OR REPLACE INTO t1(name) VALUES(?)', [name])
def select():
return cur.execute('SELECT * FROM t1').fetchall()
conn = sqlite3.connect('test')
cur = conn.cursor()
cur.execute('DROP TABLE IF EXISTS t1')
cur.execute('''CREATE TABLE IF NOT EXISTS t1(
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
)''')
insert('jack')
insert('jack')
insert('jack')
print select()
output
[(1, u'jack'), (2, u'jack'), (3, u'jack')]
INSERT or REPLACE ... will do replace only if there are collisions. And as your name column isnt collidable, this event cannot accur (at least not on name). You need to make name collidable:
CREATE UNIQUE INDEX IF NOT EXISTS iname ON t1 (name)
Also note that you dont need to have id column, because sqlite3 has ROWID on every table.

Categories

Resources