External Exam Download Resources Web Applications Games Recycle Bin

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)