-- Dear SQLiters, -- Here is schema first, table is below, -- followed by offending statement. -- you can copy and paste the entire body -- my comments are SQL compatible
----------------------------------------- -- STEP 1 -- -- create gender and handedness tables to fix possible values -- then create subject table ----------------------------------------- CREATE TABLE gender( gender TEXT PRIMARY KEY NOT NULL, description TEXT ); INSERT OR IGNORE INTO gender (gender, description) VALUES ('Male', 'male gender'); INSERT OR IGNORE INTO gender (gender, description) VALUES ('Female', 'female gender'); CREATE TABLE handedness( handedness TEXT PRIMARY KEY NOT NULL, description TEXT ); -- force dob yyyy-mm-dd or NULL CREATE TABLE subject( subjectID INT PRIMARY KEY NOT NULL, dob TEXT CHECK (dob IS date(dob)), gender TEXT REFERENCES gender(gender) ON UPDATE CASCADE, race TEXT, handedness TEXT REFERENCES handedness(handedness) ON UPDATE CASCADE ); -- STEP 2 -- CREATE TABLE MRIMetric( metricName TEXT PRIMARY KEY NOT NULL, description TEXT, units TEXT ); -- STEP 3 -- -- examType.examType = name of the table where -- to find exam specifics CREATE TABLE ExamType( examType TEXT PRIMARY KEY NOT NULL, description TEXT ); INSERT OR IGNORE INTO ExamType (examType, description) VALUES ('MRIExam', 'any MRI exam'); INSERT OR IGNORE INTO ExamType (examType, description) VALUES ('demographicExam', 'view on subject table'); INSERT OR IGNORE INTO ExamType (examType) VALUES ('educationExam'); -- assume date yyyy-mm-dd CREATE TABLE Exam( examID TEXT PRIMARY KEY NOT NULL, subjectID INTEGER NOT NULL REFERENCES subject(subjectID) ON UPDATE CASCADE ON DELETE CASCADE, examType TEXT NOT NULL REFERENCES examType(examType) ON UPDATE CASCADE, comments TEXT, date TEXT CHECK (date IS date(date)), age INTEGER ); ----------------------------------------- -- create triggers to compute age on various updates and inserts ----------------------------------------- -- automatically compute age at the time of exam when exam is inserted CREATE TRIGGER ageCalculatorOnExamInsert AFTER INSERT ON Exam FOR EACH ROW BEGIN UPDATE OR IGNORE Exam SET age = ( SELECT coalesce( strftime('%Y', NEW.date) - strftime('%Y', subject.dob) -1 + (strftime('%m-%d', NEW.date) >= strftime('%m-%d', subject.dob)), NEW.age) FROM subject WHERE subject.subjectID = NEW.subjectID ) -- this ends select statement that joins exam and subject tables WHERE Exam.examID = NEW.examID; END; -- automatically compute age at the time of exam when exam is updated CREATE TRIGGER ageCalculatorOnExamUpdate AFTER UPDATE ON Exam FOR EACH ROW BEGIN UPDATE OR IGNORE Exam SET age = ( SELECT coalesce( strftime('%Y', NEW.date) - strftime('%Y', subject.dob) -1 + (strftime('%m-%d', NEW.date) >= strftime('%m-%d', subject.dob)), NEW.age) FROM subject WHERE subject.subjectID = NEW.subjectID ) -- this ends select statement that joins exam and subject tables WHERE Exam.examID = NEW.examID; END; -- automatically compute age at the time of exam when subject.DOB is updated CREATE TRIGGER ageCalculatorOnSubjectUpdate AFTER UPDATE ON subject FOR EACH ROW BEGIN UPDATE OR IGNORE Exam SET age = ( SELECT coalesce( strftime('%Y', e.date) - strftime('%Y', NEW.dob) -1 + (strftime('%m-%d', e.date) >= strftime('%m-%d', NEW.dob)), e.age) FROM Exam e WHERE Exam.examID = e.examID ) -- this ends select statement that joins exam and subject tables WHERE Exam.subjectID = NEW.subjectID; END; -- STEP 4 -- CREATE TABLE MRIExam( examID TEXT NOT NULL REFERENCES Exam(examID) ON UPDATE CASCADE ON DELETE CASCADE, ResearchName TEXT, MRN INTEGER, pipeline TEXT, DICOMFolder TEXT, PRIMARY KEY (examID) ); CREATE TABLE MRIExamAccession( examID TEXT NOT NULL REFERENCES MRIExam(examID) ON UPDATE CASCADE ON DELETE CASCADE, accession INTEGER, UNIQUE (examID, accession) ); CREATE INDEX MRIExamAccessionIndex ON MRIExamAccession(examID); -- STEP 5 -- CREATE TABLE badMRIMetric( examID TEXT NOT NULL REFERENCES MRIExam(examID) ON UPDATE CASCADE ON DELETE CASCADE, metricName TEXT NOT NULL REFERENCES MRIMetric(metricName) ON UPDATE CASCADE, reason TEXT, PRIMARY KEY (examID, metricName) ); ----------------------------------------- -- STEP 6 -- -- create wave table ----------------------------------------- CREATE TABLE aboutWave( waveID TEXT PRIMARY KEY NOT NULL, description TEXT ); INSERT OR IGNORE INTO aboutWave (waveID, description) VALUES ('time1', 'first scan'); -- force uniqueness of subject+examType+wave. -- can not have several instances of one exam type within a wave -- given examID can be assigned to several waves CREATE TABLE wave( subjectID INT NOT NULL REFERENCES subject(subjectID) ON UPDATE CASCADE ON DELETE CASCADE, examType TEXT NOT NULL REFERENCES ExamType(examType) ON UPDATE CASCADE, waveID TEXT NOT NULL REFERENCES aboutWave(waveID) ON UPDATE CASCADE, examID TEXT NOT NULL REFERENCES Exam(examID) ON UPDATE CASCADE ON DELETE CASCADE, PRIMARY KEY (subjectID, examType, waveID) ); CREATE INDEX waveIndex ON wave(examID); ----------------------------------------- -- STEP 7 -- -- create view on subject table as demographicExam -- use subjectID as examID ----------------------------------------- CREATE VIEW IF NOT EXISTS demographicExam AS SELECT subjectID AS examID, dob, gender, race, handedness FROM subject; -- automatically add demographic exam to wave and Exam tables when subject is inserted -- use subjectID as examID CREATE TRIGGER demographicInsert AFTER INSERT ON subject FOR EACH ROW BEGIN INSERT INTO Exam (subjectID, examID, examType) VALUES (NEW.subjectID, NEW.subjectID, 'demographicExam'); INSERT INTO wave (subjectID, examType, waveID, examID) VALUES (NEW.subjectID, 'demographicExam', 'time1', NEW.subjectID); END; -- STEP 8 -- CREATE TABLE educationExam( examID TEXT NOT NULL REFERENCES Exam(examID) ON UPDATE CASCADE ON DELETE CASCADE, education INTEGER, PRIMARY KEY (examID) ); ----------------------------------------- ---------- end of schema ----------------------------------------- CREATE TABLE demographics( "subjectID" TEXT, "DOB" TEXT, "Age" TEXT, "Education" TEXT, "Gender" TEXT ); INSERT INTO "demographics" VALUES('0001','1992-05-04','23','16','Female'); INSERT INTO "demographics" VALUES('0002','1992-07-02','22','17','Female'); INSERT INTO "demographics" VALUES('0003','1986-01-02','29','13','Female'); INSERT INTO "demographics" VALUES('0004','1989-04-05','26','12','Female'); INSERT INTO "demographics" VALUES('0005','1989-10-15','25','18','Male'); INSERT INTO "demographics" VALUES('0006','1989-08-14','25','19','Female'); INSERT INTO "demographics" VALUES('0007','1990-04-02','25','14','Female'); INSERT INTO "demographics" VALUES('0008','1982-03-17','33','13','Male'); INSERT INTO "demographics" VALUES('0009','1966-03-03','49','16','Male'); INSERT INTO "demographics" VALUES('0010','1988-09-14','26','13','Female'); INSERT INTO "demographics" VALUES('0011','1987-11-22','27','14','Female'); INSERT INTO "demographics" VALUES('0012','1969-02-12','46','20','Male'); INSERT INTO "demographics" VALUES('0013','1988-05-03','27','19','Male'); INSERT INTO "demographics" VALUES('0014','1966-08-24','48','16','Female'); INSERT INTO "demographics" VALUES('0015','1970-04-20','45','17','Female'); INSERT INTO "demographics" VALUES('0016','1991-08-03','23','17','Male'); INSERT INTO "demographics" VALUES('0017','1989-12-15','25','18','Male'); INSERT INTO "demographics" VALUES('0018','1991-12-18','23','16','Male'); INSERT INTO "demographics" VALUES('0019','1989-04-24','26','20','Male'); INSERT INTO "demographics" VALUES('0020','1965-10-15','49','20','Male'); INSERT INTO "demographics" VALUES('0021','1980-01-03','35','15','Female'); INSERT INTO "demographics" VALUES('0022','1979-01-05','36','11','Male'); INSERT INTO "demographics" VALUES('0023','1990-10-28','24','16','Male'); INSERT INTO "demographics" VALUES('0024','1983-10-13','31','14','Male'); INSERT INTO "demographics" VALUES('0025','1991-07-10','23','14','Male'); INSERT INTO "demographics" VALUES('0026','1991-04-28','24','18','Male'); INSERT INTO "demographics" VALUES('0027','1988-07-05','26','18.5','Male'); INSERT INTO "demographics" VALUES('0028','1987-04-22','28','21','Male'); INSERT INTO "demographics" VALUES('0029','1988-08-04','26','18','Male'); INSERT INTO "demographics" VALUES('0030','1967-12-13','47','16','Male'); INSERT INTO "demographics" VALUES('0031','1983-11-05','31','16','Male'); -- Offending statement: PRAGMA foreign_keys=ON; INSERT OR IGNORE INTO subject(subjectID, dob, gender) SELECT subjectID, dob, gender FROM demographics; PRAGMA integrity_check; -- Roman