python sqlite foreing keys not deleting on cascade - python

So I have 2 files, a client and a db class:
import sqlite3
from os.path import isfile
class Database:
def __init__(self, db_name):
self.db_name = db_name
self.check = self.__check_db()
self.conn = sqlite3.connect(self.db_name, check_same_thread=False)
self.cursor = self.conn.cursor()
if not self.check:
self.__create_db()
def query(self, query, args=()):
self.cursor.execute(query, args)
result = self.cursor.fetchall()
self.conn.commit()
return result
def __check_db(self):
return isfile(self.db_name)
def __create_db(self):
self.cursor.executescript("""
PRAGMA FOREIGN_KEYS = ON;
CREATE TABLE utilizadores (id INTEGER PRIMARY KEY, nome TEXT, senha TEXT);
CREATE TABLE artistas (id INTEGER PRIMARY KEY, id_spotify TEXT, nome TEXT);
CREATE TABLE musicas (id INTEGER PRIMARY KEY, id_spotify TEXT, nome TEXT, id_artista INTEGER, FOREIGN KEY(id_artista) REFERENCES artistas(id) ON DELETE CASCADE);
CREATE TABLE avaliacoes (id INTEGER PRIMARY KEY, sigla TEXT, designacao TEXT);
CREATE TABLE playlists (id_user INTEGER, id_musica INTEGER, id_avaliacao INTEGER, PRIMARY KEY (id_user, id_musica), FOREIGN KEY(id_user) REFERENCES utilizadores(id) ON DELETE CASCADE, FOREIGN KEY(id_musica) REFERENCES musicas(id) ON DELETE CASCADE, FOREIGN KEY(id_avaliacao) REFERENCES avaliacoes(id) ON DELETE CASCADE);
INSERT INTO avaliacoes (id, sigla, designacao) VALUES (1, "M", "Medíocre"), (2, "m", "Mau"), (3, "S", "Suficiente"), (4, "B", "Boa"), (5, "MB", "Muito Boa");
""")
and the client;
from database import Database
db = Database("spotify.db")
db.query("insert into artistas (id_spotify, nome) values (?, ?)", ("1", "The Beatles"))
db.query("insert into musicas (id_spotify, nome, id_artista) values (?, ?, ?)", ("m1", "Hey Jude", 1))
db.query("delete from artistas where id = ?", (1,))
If I do the last query because of the foreign key it should delete the music as well but for some reason it doesn't. I don't know the reason for why it's doing it since I have PRAGMA fk = on and I'm on the same connection
artistas --> artists
musicas --> musics

PRAGMA FOREIGN_KEYS = ON operates on a per connection basis and this means that you must set it for every connection object that you obtain (if you want the behavior that it provides, otherwise don't set it because it may decrease performance).
Inside the Database class define:
def set_foreign_keys(self)
self.conn.execute("PRAGMA FOREIGN_KEYS = ON")
and use it in the client:
from database import Database
db = Database("spotify.db")
db.set_foreign_keys()
db.query("insert into artistas (id_spotify, nome) values (?, ?)", ("1", "The Beatles"))
db.query("insert into musicas (id_spotify, nome, id_artista) values (?, ?, ?)", ("m1", "Hey Jude", 1))
db.query("delete from artistas where id = ?", (1,))

Related

How do I access multiple records from multiple database tables?

I want to retrieve the Username records from tblUser and the Link records from tblResults.
import sqlite3
connUsers = sqlite3.connect("Users.db")
users = connUsers.cursor()
def create_user_tbl():
try:
users.execute(
"""CREATE TABLE tblUser (
UserID INTEGER,
Username TEXT,
Password TEXT,
PRIMARY KEY (UserID) )""")
tblUser = [
(1, 'Argon456', 'Fir3Tru0k'), (2, 'Max9', 'Thrsgdp0fnse'), (3, 'Steven', '1234')]
users.executemany("INSERT INTO tblUser VALUES (?, ?, ?)", tblUser); print("Database created")
except: print("Database table already exists")
def create_results_tbl():
try:
users.execute(
"""CREATE TABLE tblResults (
ResultsID INTEGER,
Title TEXT,
Location TEXT,
Link TEXT,
PRIMARY KEY (ResultsID) )""")
tblResults = [
(1, 'Business', 'Ayelsbury', 'www.link.com'), (2, 'Apprenticeship', 'Ealing', 'https://ealingpress.co.uk')]
users.executemany("INSERT INTO tblResults VALUES (?, ?, ?, ?)", tblResults); print("Database created")
except: print("Database table already exists")
for row in users.execute("SELECT A.Username, B.Link FROM A INNER JOIN B ON A.UserID = B.ResultsID;"):
print(row)
users.commit()
users.close()
I believe my SELECT statement is correct but I cannot test it as I do not know how to execute this command. To access multiple records from different tables, do I need to create multiple connections to each .db file? If not, would I execute the command through the first table in the SELECT statement?
import sqlite3
connection = sqlite3.connect("Users.db")
cursor = connection.cursor()
def create_user_tbl():
connection.execute(
"""CREATE TABLE tblUser (
UserID INTEGER,
Username TEXT,
Password TEXT,
PRIMARY KEY (UserID) )""")
print("Database created")
def populate_user():
users = [
(1, 'Argon456', 'Fir3Tru0k'),
(2, 'Max9', 'Thrsgdp0fnse'),
(3, 'Steven', '1234')
]
connection.executemany("INSERT INTO tblUser VALUES (?, ?, ?)", users)
def create_results_tbl():
connection.execute(
"""CREATE TABLE tblResults (
ResultsID INTEGER,
Title TEXT,
Location TEXT,
Link TEXT,
PRIMARY KEY (ResultsID) )""")
def populate_results():
results = [
(1, 'Business', 'Ayelsbury', 'www.link.com'),
(2, 'Apprenticeship', 'Ealing', 'https://ealingpress.co.uk')
]
connection.executemany("INSERT INTO tblResults VALUES (?, ?, ?, ?)", results);
if __name__ == "__main__":
# create_user_tbl()
# create_results_tbl()
# populate_user()
# populate_results()
# connection.commit()
for row in connection.execute("SELECT tblUser.Username, tblResults.Link FROM tblUser INNER JOIN tblResults ON tblUser.UserID = tblResults.ResultsID;"):
print(row)
prints
('Argon456', 'www.link.com')
('Max9', 'https://ealingpress.co.uk')

Python: Post json to MySql Database

I'm a bit at a loss for how to just push my json data to MySql. I have the cursor. Do I need to create a table first? Is there a method to simply push my json data straight in?
with open("trades.json") as f:
trades_data = json.load(f)
trades_data = reconfigure_data(trades_data)
db = mysql.connector.connect(
host="localhost",
user=os.environ.get('MYSQL_DB_USER'),
password=os.environ.get('MYSQL_DB_USER_PASS',
database='trades')
)
cursor = db.cursor()
I found the syntax that works:
cursor = db.cursor()
# create table on database
sql = "CREATE TABLE IF NOT EXISTS `test` (`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `objectid` VARCHAR(100), `type` VARCHAR(5), `ownerid` VARCHAR(100), `color` VARCHAR(15), `shape` VARCHAR(15), `size` VARCHAR(15), PRIMARY KEY (`id`) );"
print(sql)
cursor.execute(sql)
with open("trades.json") as f:
trades_data = json.load(f)
for trade in trades_data:
for right in trade['rights']:
sql = f"INSERT INTO test (objectid, type, ownerid, color, shape, size) VALUES ('{trade['objectid']}', '{trade['type']}', '{trade['ownerid']}', '{right['color']}', '{right['shape']}', '{right['size']}' )"
cursor.execute(sql)
db.commit()

SQLite x Python insert table returns "False", no idea why

I try to make a simple contact book in Python in cooperation with SQL database, and when I try to make a query, my INSERT function returns false.
Here's my declaration of tables
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtSql import QSqlDatabase, QSqlQuery
def _createContactsTable():
"""Create the contacts table in the database."""
createTableQuery = QSqlQuery()
return createTableQuery.exec(
"""
CREATE TABLE IF NOT EXISTS contacts (
id INTEGER PRIMARY KEY AUTOINCRE MENT UNIQUE NOT NULL,
short VARCHAR(40) NOT NULL,
fullname VARCHAR(50) NOT NULL,
postcode VARCHAR(50) NOT NULL,
city VARCHAR(50) NOT NULL,
street VARCHAR(50) NOT NULL,
phone VARCHAR(50),
email VARCHAR(40) NOT NULL
)
"""
)
def createConnection(databaseName):
"""Create and open a database connection."""
connection = QSqlDatabase.addDatabase("QSQLITE")
connection.setDatabaseName(databaseName)
if not connection.open():
QMessageBox.warning(
None,
"CustomersManager",
f"Błąd bazy danych: {connection.lastError().text()}",
)
return False
_createContactsTable()
return True
And, there's a query
from struktura.database import createConnection
# Create a connection
createConnection("contacts.sqlite")
# Confirm that contacts table exists
from PyQt5.QtSql import QSqlDatabase
db = QSqlDatabase.database()
db.tables()
from PyQt5.QtSql import QSqlQuery
insertDataQuery = QSqlQuery()
insertDataQuery.prepare(
"""
INSERT INTO contacts (
short,
fullname,
postcode,
city,
street,
phone,
email
)
VALUES (?, ?, ?, ?, ?, ?, ?)
"""
)
This procedure is creating a new sqlite file, but it's empty. Can't fill it with table propeties. When I made simple one with three values in table, it worked. Where is the problem?

Python SQLite3, table not showing updates

I am trying to create a database with SQLite3 in Python.
Creating a table appears to work, but whenever I try to insert data, it doesn't seem to add anything to the database as fetchall() returns nothing, However, if I try to create the ID again, it complains about
unique constraint failed.
Initialization:
import sqlite3
conn = sqlite3.connect('login.db')
c = conn.cursor()
Table Creation:
c.execute("""CREATE TABLE Login (ID INTEGER PRIMARY KEY,
First TEXT NOT NULL,
Last TEXT NOT NULL,
Middle TEXT NOT NULL,
Gender TEXT NOT NULL);""")
conn.commit()
Data Insert:
c.execute("""INSERT INTO Login VALUES (6, 'First', 'Last', 'Hello', 'Male');""")
conn.commit()
Fetching Tables:
print(c.fetchall())
c.close()
conn.close()
When dropping the table into an online reader, it also appears empty.
EDIT:
This is what is shown in the db reader, and in google sheets,
large list of blanks / ";" then this
c.fetchall() would return all of the rows from a SELECT query, which you aren't doing.
import sqlite3
conn = sqlite3.connect('login.db')
c = conn.cursor()
c.execute("""CREATE TABLE Login (ID INTEGER PRIMARY KEY, First TEXT NOT NULL, Last TEXT NOT NULL, Middle TEXT NOT NULL, Gender TEXT NOT NULL);""")
conn.commit()
c.execute("""INSERT INTO Login VALUES (6, 'First', 'Last', 'Hello', 'Male');""")
conn.commit()
c.execute("SELECT * FROM login")
print(c.fetchall())
will happily print
[(6, 'First', 'Last', 'Hello', 'Male')]
As an aside, your code is vulnerable to SQL injection attacks, and you should do
import sqlite3
conn = sqlite3.connect("login.db")
c = conn.cursor()
c.execute(
"""CREATE TABLE Login (ID INTEGER PRIMARY KEY, First TEXT NOT NULL, Last TEXT NOT NULL, Middle TEXT NOT NULL, Gender TEXT NOT NULL);"""
)
conn.commit()
c.execute(
"INSERT INTO Login (ID, First, Last, Middle, Gender) VALUES (?,?,?,?,?)",
(6, "First", "Last", "Hello", "Male"),
)
conn.commit()
c.execute("SELECT * FROM login")
print(c.fetchall())

Python SQLite3 function not printing any data

I have created a function that is supposed to send all the items, with a stock level of less than 10, in my database to a text file. But i am not receiving any data when I press the reorder button.
def Database():
global conn, cursor
conn = sqlite3.connect("main_storage.db")
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS `admin` (admin_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username TEXT, password TEXT)")
cursor.execute("CREATE TABLE IF NOT EXISTS `product` (product_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, product_name TEXT, product_qty TEXT, product_price TEXT)")
cursor.execute("CREATE TABLE IF NOT EXISTS `basket` (product_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, product_name TEXT, product_qty TEXT, product_price TEXT)")
cursor.execute("SELECT * FROM `admin` WHERE `username` = 'admin' AND `password` = 'admin'")
if cursor.fetchone() is None:
cursor.execute("INSERT INTO `admin` (username, password) VALUES('admin', 'admin')")
conn.commit()
def reorder():
global items
Database()
cursor.execute("SELECT `product_name` FROM `product` WHERE `product_qty` <= 10")
items = cursor.fetchall()
print(items)
cursor.close()
conn.close()
I expect the output to be an array of items within my database e.g. [44, 'motherboard', 9, 80] where 44 is product_id, motherboard is product_name, 9 is product_stock and 80 is product_price. I am actually getting an array with nothing in like: []
product_qty is defined as a TEXT column, so comparisons like <= will be performed between the string values of operands. This may not give the results that you expect:
>>> '8' < '10'
False
Recreate your tables with INTEGER or REAL as the column type for numeric values to get the behaviour that you want. For example:
cursor.execute("""CREATE TABLE IF NOT EXISTS `product` """
"""(product_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"""
"""product_name TEXT, product_qty INTEGER, product_price REAL)""")

Categories

Resources