SQLite Advanced
SQLite is covered in more detail here
parentchild_and_foreignkeys.py
import sqlite3
db = sqlite3.connect('parentchild.db')
### STEP 0: TURN ON FOREIGN KEY SUPPORT:
db.execute("PRAGMA foreign_keys = 1")
### STEP 1: DEFINE PARENT TABLE:
db.executescript("""CREATE TABLE IF NOT EXISTS parent (
a INT,
b TEXT,
PRIMARY KEY (a)
);""")
### STEP 2: DEFINE CHILD TABLE WITH FOREIGN KEY CONSTRAINTS:
db.executescript("""CREATE TABLE IF NOT EXISTS child (
c INT,
d REAL,
PRIMARY KEY (c, d)
FOREIGN KEY (c)
REFERENCES parent(a)
ON DELETE CASCADE
ON UPDATE CASCADE
);""")
### STEP 3: PARENT TABLE IS FIRST ENTRY POINT FOR DATA:
db.execute("INSERT OR IGNORE INTO parent(a, b) VALUES (1, 'guff');")
### STEP 4: ENTRY INTO CHILD TABLE, ENSURING FK CONSTRAINTS ARE MET:
db.executescript("""
INSERT OR IGNORE INTO child(c, d) VALUES (1, 0.99);
INSERT OR IGNORE INTO child(c, d) VALUES (1, -0.27);""")
### STEP 5: TEST WITH QUERY TO IDENTIFY WORKING DATASET:
print(db.execute("""
SELECT parent.b, child.d
FROM parent JOIN child ON parent.a == child.c
""").fetchall())
### STEP 6: DELETE A RECORD FROM PARENT TABLE:
db.execute("DELETE FROM parent WHERE b == 'guff'")
db.commit()
### STEP 7: RECORDS EQUAL TO THE FK HAVE BEEN REMOVED FROM CHILD TABLE:
print(db.execute("SELECT * FROM child").fetchall())
### OTHER OPTIONS FOR ON DELETE ON UPDATE:
############
#NO ACTION
#RESTRICT
#SET NULL
#SET DEFAULT
#CASCADE
#RESTRICT
############
sqlite_adv_a.py
from flask import Flask
import sqlite3
app = Flask(__name__)
# In this example, we will create a database
# with a foreign key constraint. The foreign
# key constraint is applied to the CHILD table,
# and this constraint references the PARENT table.
# In addition to this, you will note there is
# a COMPOSITE PRIMARY KEY below. This means that
# a COMBINATION of fields is used to UNIQUELY
# IDENTIFY any record (or tuple) in the table.
# FOREIGN KEY CONSTRAINTS help us maintain
# REFERENTIAL INTEGRITY, as when a change is made
# in a PARENT TABLE, that change can be CASCADED
# through to CHILD TABLES, so that a dataset is
# kept 'up to date' with accurate and existing data.
import os
if os.path.exists("people.db"):
os.remove("people.db")
db = sqlite3.connect('people.db')
db.cursor().executescript("""
CREATE TABLE IF NOT EXISTS customers (
f_name TEXT NOT NULL PRIMARY KEY UNIQUE
);
CREATE TABLE IF NOT EXISTS contacts (
f_name TEXT NOT NULL,
details TEXT NOT NULL,
PRIMARY KEY (f_name, details)
FOREIGN KEY (f_name)
REFERENCES customers(f_name)
ON DELETE CASCADE
ON UPDATE CASCADE
);
INSERT INTO customers (f_name) values ("mary");
INSERT INTO customers (f_name) values ("sam");
INSERT INTO contacts (f_name, details) values ("mary","0412 345 678");
INSERT INTO contacts (f_name, details) values ("sam","0412 345 678");
INSERT INTO contacts (f_name, details) values ("mary","mary@abc.com");
"""
)
try:
db.commit()
except Exception:
db.rollback()
finally:
db.close()
###----------------------- home page:
@app.route("/")
def main():
all_records_sql = "SELECT * FROM customers JOIN contacts ON customers.f_name == contacts.f_name"
html = ""
try:
db = sqlite3.connect('people.db')
#view all records:
html += "<h1>Prior to delete:</h1><br>"
html += str(db.cursor().execute(all_records_sql).fetchall()) + "<br>"
#delete a customer CASCADES changes so that customer's contact methods also deleted:
db.cursor().execute("DELETE FROM customers WHERE f_name == 'mary'")
#view all records (again) to see change:
html += "<h1>After deletion:</h1><br>"
html += str(db.cursor().execute(all_records_sql).fetchall()) + "<br>"
except Exception as error_msg:
html = str(error_msg)
finally:
db.close()
return html
app.run(debug=True)