Python SQLite3 query concatenating two values - python

I have a database (student.db) that contains one table (Students).
Each row in students contains (ID, FName, LName).
There is an existing row (0, John, Doe).
I want to be able to enter a variable as a full name, find that name in the database, and delete that row.
Here's what I came up with... but it doesn't seem to work:
import sqlite3
conn = sqlite3.connect('student.db')
c = conn.cursor()
selection = "John Doe"
c.execute('DELETE FROM Students WHERE (FName + " " + LName =?', (selection,))
I don't get an error message. I'm guessing that's because it simply doesn't find any entries that match the WHERE clause.
Is there a way to properly write a WHERE clause that incorporates multiple values from the row of interest?
I am very new to this, so I apologize if this is a dumb question. I'm trying to make a Kivy app that creates a ListView of student names. Then you can select a student from the list and click "Delete" to remove that student from the ListView dictionary and from the database.

For concatenation most SQL implementations use '||' operator. See SQLite docs.
c.execute("DELETE FROM Students WHERE (FName || ' ' || LName = ?", (selection,))

Working with names is difficult but I think I'm over-thinking your question. Assuming that you just want to query two fields, you can split the name into a first_name and a last_name, and delete from the DB where that combination is satisfied.
selection = "John Doe"
first_name, last_name = selection.split()
query = """
DELETE FROM Students
WHERE FName = ? AND LName = ?
"""
c.execute(query, (first_name, last_name))
conn.commit()

Related

Python MySql selecting from empty string

I'm trying to select from a table so that the parameter I input can be nothing but it still will select everything
name = ""
mycursor.execute('SELECT * FROM table WHERE name LIKE "%%%s%%"' (name, ))
I was hoping to have if name is something like "", then everything in the table will be fetched.
With LIKE it will not be possible , however you can achieve it using REGEXP
name = "John Doe"
regexp='^.*$'
value = (regexp if name=="" else name)
query = "SELECT * FROM mysql.user WHERE name REGEXP '{}' ;".format(value)
print(query)
Note: However be wary that if you are looking for a single user, and if there are other user names that matches the string Like "John Doe1" it will return both the entries

Calling three tables to insert data. (sqlite3/python)

I have normalised three tables (Product, ProductType and ProductGender) and I'm looking to call them in my main program so that the user can successfully enter values and the data be stored in the correct table.
Here are the SQL tables being created
def create_product_table():
sql = """create table Product
(ProductID integer,
Name text,
primary key(ProductID))"""
create_table(db_name, "Product", sql)
def create_product_type_table():
sql = """create table ProductType
(ProductID integer,
Colour text,
Size text,
Gender text,
AmountInStock integer,
Source text,
primary key(ProductID, Colour, Size, Gender)
foreign key(Gender) references ProductGender(Gender)
foreign key(ProductID) references Product(ProductID))"""
create_table(db_name, "ProductType", sql)
def create_product_gender_table():
sql = """create table ProductGender
(Gender text,
Price text,
primary key(Gender))"""
create_table(db_name, "ProductGender", sql)
Here are the SQL subroutines
def insert_data(values):
with sqlite3.connect("jam_stock.db") as db:
cursor = db.cursor()
sql = "insert into Product (Name, ProductID) values (?,?)"
cursor.execute(sql,values)
db.commit()
def insert_product_type_data(records):
sql = "insert into ProductType(Amount, Size, Colour, Source) values (?,?,?,?)"
for record in records:
query(sql,record)
def insert_product_gender_data(records):
sql = "insert into ProductGender(Gender, Price) values (?,?)"
for record in records:
query(sql, records)
def query(sql,data): #important
with sqlite3.connect("jam_stock.db") as db:
cursor = db.cursor()
cursor.execute("PRAGMA foreign_keys = ON") #referential integrity
cursor.execute(sql,data)
db.commit()
Below is the code where the user will enter the values.
if ans=="1": #1=to option 'Add Stock'
a = input("Enter Gender: ")
b = float(input("Enter Price: "))
c = int(input("Enter ProductID: "))
d = input("Enter Name: ")
e = input("Enter Size: ")
f = input("Enter Colour: ")
g = input("Enter Source: ")
h = input("Enter Amount: ")
#code calling tables should be here
Help is gratefully appreciated. Seriously not sure how to link the 3 tables with the user's input.
This is what I did before I normalised the database. So the one table in 'Product' would be updated instead of adding an already existing product. Obviously that has changed now, since I've created two new tables but I can't successfully add a product let alone edit one.
def update_product(data): #subroutine for editing stock
with sqlite3.connect("jam_stock.db") as db:
cursor = db.cursor()
sql = "update Product set Name=?, Price=?, Amount=?, Size=?, Colour=?, Source=?, Gender=? where ProductID=?"
cursor.execute(sql,data)
db.commit()
Given the code you show above, and assuming (BIG assumption, see later!) that the user never enters data for existing records, the following code should do it:
query('insert into Product (Name, ProductID) values (?,?)',
[d, c])
query('insert into ProductGender (Gender, Price) values (?,?)',
[a, b])
query('insert into ProductType (ProductID, Colour, Size, Gender, '
AmountInStock, Source) values (?,?,?,?,?,?)',
[c, f, e, a, h, g])
Your use of arbitrary single-letter variable names makes this very hard to follow, of course, but I think I got the correspondence right:-).
Much more important is the problem that you never tell us what to do if the user enters data for an already existing record in one or more of the three tables (as determined by the respective primary keys).
For example, what if Product already has a record with a ProductID of foobar and a Name of Charlemagne; and the user enters ProductID as foobar and a Name of Alexandre; what do you want to happen in this case? You never tell us!
The code I present above will just fail the whole sequence because of the attempt to insert a new record in Product with an already-existing primary key; if you don't catch the exception and print an error message this will in fact crash your whole program.
But maybe you want to do something completely different in such cases -- and there are so many possibilities that we can't just blindly guess!
So please edit your Q to clarify in minute detail what's supposed to happen in each case of primary key "duplication" in one or more table (unless you're fine with just crashing in such cases!-), and the SQL and Python code to make exactly-that happen will follow. But of course we can't decide what the semantics of your program are meant to be...!-)

mysql.connector select query with binary values

Using Python's mysql.connector, how can I select all records that match a tuple?
For example:
ids = (b'6TRsHMzWSrq0zeembo0Vbg',
b'7Qoq53lKTk-RZOi830t3MA',
b'7ZGO9S3DTcGHjwrfpV0E0A')
And then the query would do something like:
query = SELECT first_name
FROM users
WHERE id = (ids)
Returning records for all users whose ID appears in the tuple
Try doing this
query = "SELECT first_name FROM users WHERE id IN " + str(list(ids))
cursor.execute(query)
On second thoughts, the following should also work
query = "SELECT first_name FROM users WHERE id IN " + str(ids)
EDIT
OP mentions in comments that the ids are binary data returned from a previous query. In which case, taking hint from this answer and using BINARY operator, the following query should work
query = "SELECT first_name FROM users WHERE BINARY id IN " + str(ids) ;

Trying to search a column on SQLite Python so that it only returns the information searched

New to Python and Databases
I have a database table set up with a column of usernames. I want the user to be able to search through the table via a raw_input and only return the values which are associated with that user name.
E.g. user searches for Bill and it only displays Bill's records ordered by a specified column
This is what I have so far but its obviously VERY wrong, hope someone can help:
def find_me(db, column_name):
db = sqlite3.connect(db)
cursor = db.cursor()
name = raw_input("Please enter your username: ")
cursor.execute("SELECT name FROM username WHERE name=?", (name,))
cursor.execute("SELECT * FROM username ORDER BY "+column_name+" ASC")
name = cursor.fetchone()
next = cursor.fetchone()
Thank you in advance
You want to make the query similar to the following:
cursor.execute("SELECT name FROM username WHERE name=?", (name,))
This uses query parameters, so it's correctly escaped for the data provided. Then just adapt this to SELECT * and whatever else you want from the result.
Try working with this:
name = raw_input("Please enter your username: ")
query = "SELECT * FROM username WHERE name=? ORDER BY {0}".format(column_name)
cursor.execute(query, (name,))
for row in cursor:
print row

Getting the id of the last record inserted for Postgresql SERIAL KEY with Python

I am using SQLAlchemy without the ORM, i.e. using hand-crafted SQL statements to directly interact with the backend database. I am using PG as my backend database (psycopg2 as DB driver) in this instance - I don't know if that affects the answer.
I have statements like this,for brevity, assume that conn is a valid connection to the database:
conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
Assume also that the user table consists of the columns (id [SERIAL PRIMARY KEY], name, country_id)
How may I obtain the id of the new user, ideally, without hitting the database again?
You might be able to use the RETURNING clause of the INSERT statement like this:
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING *")
If you only want the resulting id:
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)
RETURNING id")
[new_id] = result.fetchone()
User lastrowid
result = conn.execute("INSERT INTO user (name, country_id) VALUES ('Homer', 123)")
result.lastrowid
Current SQLAlchemy documentation suggests
result.inserted_primary_key should work!
Python + SQLAlchemy
after commit, you get the primary_key column id (autoincremeted) updated in your object.
db.session.add(new_usr)
db.session.commit() #will insert the new_usr data into database AND retrieve id
idd = new_usr.usrID # usrID is the autoincremented primary_key column.
return jsonify(idd),201 #usrID = 12, correct id from table User in Database.
this question has been asked many times on stackoverflow and no answer I have seen is comprehensive. Googling 'sqlalchemy insert get id of new row' brings up a lot of them.
There are three levels to SQLAlchemy.
Top: the ORM.
Middle: Database abstraction (DBA) with Table classes etc.
Bottom: SQL using the text function.
To an OO programmer the ORM level looks natural, but to a database programmer it looks ugly and the ORM gets in the way. The DBA layer is an OK compromise. The SQL layer looks natural to database programmers and would look alien to an OO-only programmer.
Each level has it own syntax, similar but different enough to be frustrating. On top of this there is almost too much documentation online, very hard to find the answer.
I will describe how to get the inserted id AT THE SQL LAYER for the RDBMS I use.
Table: User(user_id integer primary autoincrement key, user_name string)
conn: Is a Connection obtained within SQLAlchemy to the DBMS you are using.
SQLite
======
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
# Execute within a transaction (optional)
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.lastrowid
txn.commit()
MS SQL Server
=============
insstmt = text(
'''INSERT INTO user (user_name)
OUTPUT inserted.record_id
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()
MariaDB/MySQL
=============
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm) ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = conn.execute(text('SELECT LAST_INSERT_ID()')).fetchone()[0]
txn.commit()
Postgres
========
insstmt = text(
'''INSERT INTO user (user_name)
VALUES (:usernm)
RETURNING user_id ''' )
txn = conn.begin()
result = conn.execute(insstmt, usernm='Jane Doe')
# The id!
recid = result.fetchone()[0]
txn.commit()
result.inserted_primary_key
Worked for me. The only thing to note is that this returns a list that contains that last_insert_id.
Make sure you use fetchrow/fetch to receive the returning object
insert_stmt = user.insert().values(name="homer", country_id="123").returning(user.c.id)
row_id = await conn.fetchrow(insert_stmt)
For Postgress inserts from python code is simple to use "RETURNING" keyword with the "col_id" (name of the column which you want to get the last inserted row id) in insert statement at end
syntax -
from sqlalchemy import create_engine
conn_string = "postgresql://USERNAME:PSWD#HOSTNAME/DATABASE_NAME"
db = create_engine(conn_string)
conn = db.connect()
INSERT INTO emp_table (col_id, Name ,Age)
VALUES(3,'xyz',30) RETURNING col_id;
or
(if col_id column is auto increment)
insert_sql = (INSERT INTO emp_table (Name ,Age)
VALUES('xyz',30) RETURNING col_id;)
result = conn.execute(insert_sql)
[last_row_id] = result.fetchone()
print(last_row_id)
#output = 3
ex -

Categories