Model a Table that depends on a set of values in referenced table that can or not be present at the same time - sql

I have a table 'medical_observations' that in one field references other table 'sypstoms_at_arriving' that describes a list of possible symptoms.
CREATE TABLE `patients`(
id_patient INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(25) ,
address VARCHAR(50) ,
CONSTRAINT `uc_Info_Patient` UNIQUE (`id_patient`)
);
INSERT INTO `patients` values (1,'joe','joe´s address');
INSERT INTO `patients` values (2,'moe','moe´s address');
INSERT INTO `patients` values (3,'karl','karle´s address');
INSERT INTO `patients` values (4,'lenny','lenny´s address');
CREATE TABLE `symptoms_at_arrival` (
symptom_at_arrival varchar(30) primary key
);
INSERT INTO `symptoms_at_arrival` values ('vomit');
INSERT INTO `symptoms_at_arrival` values ('urine');
INSERT INTO `symptoms_at_arrival` values ('dizziness');
INSERT INTO `symptoms_at_arrival` values ('convulsion');
CREATE TABLE `medical_observations`(
id_medical_observation INTEGER NOT NULL PRIMARY KEY,
id_patient INTEGER NOT NULL,
symptom_at_arrival VARCHAR(30),
FOREIGN KEY (id_patient) references `patients` (id_patient),
FOREIGN KEY (symptom_at_arrival) references `symptoms_at_arrival` (symptom_at_arrival ),
CONSTRAINT `uc_Info_medical_Observation` UNIQUE (`id_medical_observation`,`id_patient`)
);
My doubt is how to model or store th case when patient has several symptoms... and not just one.
If that would be the case the name of symptom would be enough...
But if patient show several symptoms at the same time?
Update
I have done a sqlfiddle, I was thinking to add a kind of table with 1's and 0's representing if patient shows certain symptom... Would that be correct?

You'll have to make connection in the foreign keys
|patient| |medical_observations| |symptoms_at_arriving|
--------- ---------------------- ----------------------
**id** 1 ----| **id_medical_observation** |-----1 **id**
name |-M **id_patient** | symptom_at_arrival
**symptom_at_arrival** M---|
Try this, don't have mysql here to test, making table multi primary key to support multiple symptoms at same time
CREATE TABLE `symptoms_at_arriving` (
id integer not null primary key autoincrement,
symptom_at_arrival varchar(30)
);
INSERT INTO `symptom_at_arrival' values ('vomit');
INSERT INTO `symptom_at_arrival` values ('urine');
INSERT INTO `symptom_at_arrival` values ('dizziness');
INSERT INTO `symptom_at_arrival` values ('convulsion');
CREATE TABLE `medical_observations`(
id_medical_observation INTEGER NOT NULL,
id_patient INTEGER NOT NULL,
symptom_at_arrival integer not null,
FOREIGN KEY (id_patient) references `patients` (id_patient),
FOREIGN KEY (symptom_at_arrival) references `symptoms_at_arriving` (symptom_at_arrival,
PRIMARY KEY (id_medical_observation, id_patient, symptom_at_arrival)
);

Related

Many-to-Many Link Table Foreign Key Modeling in SQLite

I have the following two tables in SQLite:
CREATE TABLE `Link` (
`link_id` integer NOT NULL,
`part_id` integer NOT NULL,
CONSTRAINT `link_pk` PRIMARY KEY(`link_id`,`part_id`)
);
CREATE TABLE `Main` (
`main_id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,
`link_id` integer NOT NULL REFERENCES `Link`(`link_id`)
);
INSERT INTO `Link` (link_id, part_id) VALUES (1,10);
INSERT INTO `Link` (link_id, part_id) VALUES (1,11);
INSERT INTO `Link` (link_id, part_id) VALUES (1,12);
INSERT INTO `Link` (link_id, part_id) VALUES (2,15);
INSERT INTO `Main` (main_id, link_id) VALUES (1,1);
INSERT INTO `Main` (main_id, link_id) VALUES (2,1);
INSERT INTO `Main` (main_id, link_id) VALUES (3,2);
Many Main rows may reference the same link id, and many Link rows may have the same link id, such that select * from Main natural join Link where main_id=1 will return N rows, and select * from Main where link_id=1 will return K rows. The link id is important, and the original data each main has 1 link id, and each link has N part ids.
Using the schemas above, I am unable to insert any rows in Main due to the foreign key constraint (foreign key mismatch - "Main" referencing "Link": INSERT INTO Main (main_id, link_id) VALUES (1,1);), presumably because of the composite key requirement. I can get this to work by removing the foreign key constraint, but then I am obviously missing a constraint. Reversing the direction of the key wouldn't work either since, as stated above, it's a Many-to-Many relationship. Is there a way to properly model this in SQLite with a constraint that at least one row exists in Link for each link_id in Main?
I would propose a different design.
Each of the 2 entities link_id and part_id should be the primary key in 2 tables, something like:
CREATE TABLE Links (
link_id INTEGER PRIMARY KEY,
link_description TEXT
);
CREATE TABLE Parts (
part_id INTEGER PRIMARY KEY,
part_description TEXT
);
Then, create the junction table of the above tables (like your current Link table):
CREATE TABLE Links_Parts (
link_id INTEGER NOT NULL REFERENCES Links(link_id),
part_id INTEGER NOT NULL REFERENCES Parts(part_id),
PRIMARY KEY(link_id, part_id)
);
and the table Main:
CREATE TABLE Main (
main_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
link_id INTEGER NOT NULL REFERENCES Links(link_id)
);
All the relations are there and you have referential integrity guaranteed if you set foreign key support:
PRAGMA foreign_keys = ON;
See a simplified demo.

SQL ORA-02291: integrity constraint violated - parent key not found

I have encountered some problem with SQL foreign key.
Here are my table and insert SQL.
create table passenger_card2
(
phone char(20) primary key,
name char(20)
);
create table card
(
card_num char(20) primary key,
balance number(10,2),
cvn char(20)
);
create table passenger_card1
(
sin integer primary key,
user_id char(20) not null unique,
phone char(20),
card_num char(20) unique,
foreign key(phone) references passenger_card2,
foreign key (card_num) references card
);
And here are my INSERT statements:
INSERT INTO PASSENGER_CARD2 VALUES ( '111222333' , 'Ace');
INSERT INTO CARD VALUES ( '1000' , '100.1' , '110');
INSERT INTO PASSENGER_CARD1 VALUES ('100', 'aaaa', '111222333', '1000');
However, I get an error when I tried to insert PASSENGER_CARD1 data:
SQL ORA-02291: integrity constraint violated - parent key not found
I am not sure why my foreign key is wrong?
I am not sure if this is going to be right but you should make the table 2 first before you create the first table. The database is confused because it wouldnt make sense telling them that theres gonna be a foreign key in the second table but the table isnt created. Run the code for the second table first and then run the code for the first table.

PostgreSQL UNIQUE constraint and REFERENCES

Let's say I have a table tree and a table special_tree
CREATE TABLE tree VALUES (name VARCHAR(32) UNIQUE NOT NULL PRIMARY KEY,
type VARCHAR(32) NOT NULL);
CREATE TABLE special_tree VALUES (name NOT NULL REFERENCES tree(name),
treat_date DATE,
id INT NOT NULL PRIMARY KEY);
So I have a table containing a list of trees with unique names BUT I want to say that a tree can have multiple 'treat_date' (for various reasons).
Since tree(name) is unique I can't add 2 same name in special_tree.
Is the only solution is to remove unique from tree and then add everywhere i handle the tree table an IF statement to check if name isn't already there? (IF EXISTS (SELECT name FROM tree where tree.name = ...))
If you consider the column name of the table tree it doesn't mean that all referenced columns also should have unique values. Take a look at this example
the best solution for this is (for MySQL):
CREATE TABLE tree VALUES (
id_t int(11) NOT NULL auto_increment,
name VARCHAR(32) NOT NULL,
type VARCHAR(32) NOT NULL,
CONSTRAINT tree_pk PRIMARY KEY (id_t));
CREATE TABLE special_tree VALUES (
id_st int(11) NOT NULL auto_increment,
id_t NOT NULL REFERENCES tree(id_t),
treat_date DATE,
CONSTRAINT special_tree_pk PRIMARY KEY (id_st));
for PostgreSQL:
CREATE TABLE tree VALUES (
id_t serial primary key,
name VARCHAR(32) NOT NULL,
type VARCHAR(32) NOT NULL);
CREATE TABLE special_tree VALUES (
id_st serial primary key,
id_t NOT NULL REFERENCES tree(id_t),
treat_date DATE);

Reusing a constraint while creating a table

While creating a table how can I reuse a constraint that has been mentioned for a previous column?
create table ticket_details(
from_stn char(3)
constraint chk check(from_stn in ('vsh','mas','ndl'))
constraint nn NOT NULL,
to_stn char(3)
constraint nn1 NOT NULL, (instead of crea)
seat_no number(3)
constraint PK primary key,
);
A domain constraint will be enforced on any instance of the domain. Also: upon change, you'll have to change it in only one place. (the syntax might differ slightly between implementations)
CREATE DOMAIN THE_STN CHAR(3) constraint THE_STN_check_da_value check(VALUE in ('vsh','mas','ndl'))
;
CREATE table ticket_details
( seat_no INTEGER NOT NULL PRIMARY KEY
, from_stn THE_STN NOT NULL
, to_stn THE_STN
);
INSERT INTO ticket_details(seat_no,from_stn,to_stn) VALUES (1, 'vsh', 'ndl' ); -- succeeds
INSERT INTO ticket_details(seat_no,from_stn,to_stn) VALUES (2, 'vsh', NULL ); -- succeeds
INSERT INTO ticket_details(seat_no,from_stn,to_stn) VALUES (2, 'lol', 'mas' ); -- fails
Reusing a constraint for another column is not possible. You have to define it for other column if you want

Need Help Writing SQL Trigger

Been trying to write this trigger but I can't really work it out..
What I need to do:
Delete an item from the item table but at the same time delete any questions which are associated with the item as well as any questionupdates associated with that question. These deleted records then need to be stored in archived tables with a time of deletion as well as the ID of the operator that deleted them.
A question may have several updates associated with it as may an item have many questions relating to it.
I've put all the schema in the SQL fiddle as it's a lot easier to work on in there but I'll put it in here if needed.
The link to the SQL fiddle:
http://sqlfiddle.com/#!1/1bb25
EDIT: Thought I might as well put it here..
Tables:
CREATE TABLE Operator
(
ID INTEGER NOT NULL PRIMARY KEY,
Name VARCHAR(40) NOT NULL
);
CREATE TABLE Item
(
ID INTEGER NOT NULL PRIMARY KEY,
Name VARCHAR(40) NOT NULL
);
CREATE TABLE Faq
(
ID INTEGER NOT NULL PRIMARY KEY,
Question VARCHAR(150) NOT NULL,
Answer VARCHAR(2500) NOT NULL,
ItemID INTEGER,
FOREIGN KEY (ItemID) REFERENCES Item(ID)
);
CREATE TABLE Customer
(
ID INTEGER NOT NULL PRIMARY KEY,
Name VARCHAR(20) NOT NULL,
Email VARCHAR(20) NOT NULL
);
CREATE TABLE Question
(
ID INTEGER NOT NULL PRIMARY KEY,
Problem VARCHAR(1000),
AskedTime TIMESTAMP NOT NULL,
CustomerID INTEGER NOT NULL,
ItemID INTEGER NOT NULL,
FOREIGN KEY (ItemID) REFERENCES Item(ID),
FOREIGN KEY (CustomerID) REFERENCES Customer(ID)
);
CREATE TABLE qUpdate
(
ID INTEGER NOT NULL PRIMARY KEY,
Message VARCHAR(1000) NOT NULL,
UpdateTime TIMESTAMP NOT NULL,
QuestionID INTEGER NOT NULL,
OperatorID INTEGER,
FOREIGN KEY (OperatorID) REFERENCES Operator(ID),
FOREIGN KEY (QuestionID) REFERENCES Question(ID)
);
-- Archive Tables
CREATE TABLE DeletedQuestion
(
ID INTEGER NOT NULL PRIMARY KEY,
Problem VARCHAR(1000),
AskedTime TIMESTAMP NOT NULL,
CustomerID INTEGER NOT NULL,
ItemID INTEGER NOT NULL
);
CREATE TABLE DeletedqUpdate
(
ID INTEGER NOT NULL PRIMARY KEY,
Message VARCHAR(1000) NOT NULL,
UpdateTime TIMESTAMP NOT NULL,
Question INTEGER NOT NULL
);
CREATE TABLE DeletedItem
(
ID INTEGER NOT NULL PRIMARY KEY,
Name VARCHAR(40) NOT NULL,
OperatorDeleteID INTEGER NOT NULL,
FOREIGN KEY (OperatorDeleteID) REFERENCES Operator(ID)
);
Some samples inserts for testing
--Product Inserts
INSERT INTO Item (ID, Name) VALUES (1, 'testitem1');
INSERT INTO Item (ID, Name) VALUES (2, 'testitem2');
--Operator Inserts
INSERT INTO Operator (ID, Name) VALUES (1, 'testname1');
INSERT INTO Operator (ID, Name) VALUES (2, 'testname2');
--Faq Inserts
INSERT INTO Faq (ID, Question, Answer, ItemID) VALUES (1, 'testq1', 'testa1', 1);
INSERT INTO Faq (ID, Question, Answer, ItemID) VALUES (2, 'testq2', 'testa2', 2);
-- Customer Inserts
INSERT INTO Customer (ID, Name, Email) VALUES (1, 'testcust1', 'testemail1');
INSERT INTO Customer (ID, Name, Email) VALUES (2, 'testcust2', 'testemail2');
-- Question Inserts
INSERT INTO Question (ID, Problem, AskedTime, CustomerID, ItemID) VALUES (1,'testproblem1','2012-03-14 09:30',1,1);
INSERT INTO Question (ID, Problem, AskedTime, CustomerID, ItemID) VALUES (2,'testproblem1','2012-07-14 09:30',2,1);
INSERT INTO qUpdate (ID, Message, UpdateTime, OperatorID, QuestionID) VALUES (1, 'test1','2012-05-14 09:30', 1, 1);
INSERT INTO qUpdate (ID, Message, UpdateTime, OperatorID, QuestionID) VALUES (2, 'test2','2012-08-14 09:30', 2, 1);
The first thing to do is to understand that in PostgreSQL, a CREATE TRIGGER statement binds a trigger function to one or more operations on a table, so let's start with the syntax of the function. You can write trigger functions in various scripting languages, but the most common is plpgsql. A simple function might look like this:
CREATE OR REPLACE FUNCTION Question_delete_trig_func()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO DeletedQuestion
SELECT OLD.*;
RETURN OLD;
END;
$$;
To run this after deletes:
CREATE TRIGGER Question_delete_trig
AFTER DELETE ON Question
FOR EACH ROW EXECUTE PROCEDURE Question_delete_trig_func();
That should be enough to get you started.
You should have a trigger like this for each table from which deleted rows should be saved. Then you need to determine how you will make the deletes happen. You could just define the appropriate foreign keys as ON DELETE CASCADE and let PostgreSQL do it for you.