SQL database (Firebird): problem with a foreign key - sql

My SQL database (Firebird) has a table named tTransaction. It contains two columns, senderFK and receiverFK. There are three other tables, tBufferStock, tFacility and tOutsideLocation.
A sender or a receiver can be either a buffer stock, our own facility or a location outside.
My problem is that I don't know how to let senderFK or receiverFK reference the right table.
I've thought of a new table between sender and the three possible senders with an ID, a number between 1 and 3 for the table and the referenced ID within this table, but actually that doesn't solve the problem. Any ideas?
Norbert

What you're trying to do cannot be done in SQL. You cannot reference up to three different tables with a single FK.
What you need to do would be:
create additional columns senderBufferstockFK, senderFacilityFK, and senderOutsideLocationFK
connect those to the appropriate tables
have a check constraint (if supported) or a trigger or some other mechanism on your main table to make sure only one of those three has a value at any given time
This would mean, at any given time, only one of the three "fk" column could have a value on it, but each FK column would be a specific FK to a specific table.
You could put this directly into the table you're talking about, or you could externalize this into a separate table and from your main table just reference that "intermediary" table, and from there have these three FK
YourTable.SenderFK --> Intermediary.PK
Intermediary.SenderBufferstockFK --> tBufferstock.ID
Intermediary.SenderFacilityFK --> tFacility.ID
Intermediary.SenderOutsideLocationFK --> tOutsideLocation.ID
Or you can just drop the FK-relationship, but that's definitely NOT a good idea!
Marc

Try the following schema:
tSenderReceiver (type INT, id INT, PRIMARY KEY (type, id))
tTransaction (id INT PRIMARY KEY, senderType INT, senderId INT, receiverType INT, receiverID INT,
FOREIGN KEY (senderType, senderID) REFERENCES tSenderReceiver,
FOREIGN KEY (receiverType, receiverID) REFERENCES tSenderReceiver
)
tBufferStock (type INT, id INT,
CHECK (type = 1),
PRIMARY KEY (type, id),
FOREIGN KEY (type, id) REFERENCES tSenderReceiver
)
tFacility (type INT, id INT,
CHECK (type = 2),
PRIMARY KEY (type, id),
FOREIGN KEY (type, id) REFERENCES tSenderReceiver
)
tOutsideLocation (type INT, id INT,
CHECK (type = 3),
PRIMARY KEY (type, id),
FOREIGN KEY (type, id) REFERENCES tSenderReceiver
)

SQL does not support a foreign key of the form "either this column in table X or that column in table Y". You can:
Refactor your database so that all three possible foreign key tables are combined into one, possibly called tCounterParty. This is definitely appropriate if the structure of those tables is identical or very similar. If they are not similar you can still take this approach and use three other tables, linked to tCounterParty, to hold the varying information.
Move your referential integrity from a foreign key into a trigger, if supported by your database.

can't you use 3 columns for sender and 3 for receiver? so you'll have bufferSenderFK, facilitySenderFK and facilitySenderFK. for a single transaction, 1 column can be used and other two will be null.

Related

PostgreSQL ensure data integrity for shared primary key

Let's say we want to use globally unique id and find the type of entity using it:
CREATE TABLE identity (
id serial PK NOT NULL,
type IdentityEnum NOT NULL,
UNIQUE (id, type)
);
CREATE TABLE user (
id integer PK NOT NULL REFERENCES identity (id),
type IdentityEnum NOT NULL,
UNIQUE (id, type)
ALTER TABLE user
add constraint identity_fk
foreign key (id, type)
REFERENCES identity (id, type);
);
CREATE TABLE animal (
id integer PK NOT NULL REFERENCES identity (id),
type IdentityEnum NOT NULL,
UNIQUE (id, type)
ALTER TABLE animal
add constraint identity_fk
foreign key (id, type)
REFERENCES identity (id, type);
);
To ensure that user or animal tables will have one to one relation to identity:
it's will not be possible by more that one table to point at the same identity PK
We are forced to add additional type column for each table, add UNIQUE (id, type) and add FK from each table to identity.
Questions:
Is there another way to design database with a shared by multiple tables id without the need for type?
How to do joins if you have only id and don't know the type?
1
You do not need the type columns in any table. The type will appear in a view by the fact that the complementary data are stored into the animal or user table. This is known as an inherited data modeling. The "IDENTITY" table is the father table, while user and animal are children tables.
But to make it working properly you need to add triggers for INSERT / UPDATE that exclude the same ID velue to be present in the two child tables.
2
Use the view

SQL How to not insert duplicated values

I'm trying to create a procedure that inserts data into a table of registers but i don't want to repeat the second parameter, this is the table
CREATE TABLE Inscription
(
idClass INT references tb_class,
idStudent INT references tb_student,
)
The idea is that a student (idStudent) can register in various classes but not in the same class (idClass), I tried to add a unique constraint in the idStudent column but that only allows a student to register in one single class.
I always suggest that all tables have a numeric primary key. In addition, your foreign key references are not correct. And what you want to do is add a unique constraint.
The exact syntax depends on the database. The following is for SQL Server:
CREATE TABLE Inscriptions (
idInscription int identity(1, 1) primary key
idClass int references tb_classes(idClass),
idStudent int references tb_students(idStudnt)
unique (idClass, idStudent)
);
Notice that I name the tables as the plural of the entity, but the id using the singular.
The Inscriptions table probably wants other columns as well, such as the date/time of the inscription, the method, and other related information.
You are looking to create a constraint on your table that includes both columns idClass and idStudent.
Once that constraint is created, an attempt to insert duplicate class/student will result in an error being raised.
As your table does not seem to include a primary key, you would better make that constraint your primary key.
NB : you did not tell which RDBMS you are using hence cannot give you the exact syntax to use...
Your unique key needs to encompass both idClass and idStudent, so any particular combination cannot repeat itself.

Adding multiple foreign keys in column

Is there a way to store multiple values in a column that has a foreign key constraint?
Let's say I have a states table and a project table. Project table has a foreign key constraint with states table. Now we are implementing the same project in three different states. How can I select multiple states?
Sample
Create table states (
Stateid int identity primary key,
State varchar(100)
);
Projects Table
Create table projects (
ProjId int primary key identity,
ProjTitle varchar (100),
Budget decimal,
);
How can I insert multiple values in projects states table?
Based on TPHE answer lets me create another table called projectstates
Create table projectstates(
projStatid int identity primary key,
stateid int,
ProjId int
constraint fk_ProjId foreign key (ProjId) references Projects(ProjId),
constraint fk_stateid foreign key (stateid) references states(StateId)
);
Now how can i insert data in ProjectStates while adding project to the project table?
The best way I've found to do this is to create the second table with no foreign key constraint at first. Then you can populate both tables with the data, then introduce the constraint afterwards - assuming the data in the tables complies with the constraint.
Also, if a many to many relationship exists, add in a mapping table to allow this.
It would break some basic rules of database design to add multiple values. You should create a new table that has a one to many relationship with the states table (each state can have multiple values in the new table) and contains a column for the associated project IDs (also with a one-to-many relationship). Then you would join from the states table to the new table and then to the projects table or vice versa. More info on how and why to design databases in this way.

Creating relation between tables in Movie Database

I have created a movie database that contain following tables :
1.Film
2.People
3.Genres
4.Role
5.Users
Here is my sql
create table Film ( id INT(30),title varchar(30),images varchar(30)
primary key (id));
create table people(id INT(30),Fname varchar(30),Lname varchar(30),
primary key (id));
create table Role(id INT(30), name varchar(30),
primary key(id));
i want create relation between Film,People and Role table.SO my Question is do i need to create a table to make relation between those table and is it necessary to use auto_increment for id column?
You'd want to create some tables like:
FilmRole( FilmId INT, RoleId INT) these 2 columns would make your PK and they are also FK's to their
FilmPeople (FilmId INT, PeopleId INT) respective source tables.
FilmUsers( FilmId INT, UserId INT)
You could add a single IDENTITY (for SQL Server for example) column to each table if you wanted but in this particular case a 2 column PK is adequate as these tables simply point to other records.
You need to alter your table and add in a foreign key (Primary key in one table and attribute in another). Examples how to do it here! http://www.w3schools.com/sql/sql_foreignkey.asp
do i need to create a table to make relation between those table ?
YES ! to enforce Referential integrity read this
is it necessary to use auto_increment for id column?
Depends but it is most prefered way of creating a PK on a table

Could a foreign key be defined, whose fields belong to different but related tables?

Given four tables:
CREATE TABLE LIST_A (
A INT,
PRIMARY KEY (A)
)
CREATE TABLE LIST_B (
A INT,
B INT,
PRIMARY KEY (A, B),
FOREIGN KEY (A) REFERENCES LIST_A (A)
)
CREATE TABLE LIST_C (
C INT,
A INT,
PRIMARY KEY (C),
FOREIGN KEY (A) REFERENCES LIST_A (A)
)
CREATE TABLE LIST_D (
C INT,
D INT,
B INT,
PRIMARY KEY (C, D),
FOREIGN KEY (C) REFERENCES LIST_C (C)
)
I want to add another constraint: Given a row in LIST_D, whose primary is (C0,D0), and its parent row in LIST_C, whose primary key is C0, the pair (LIST_C.A, LIST_D.B) must reference LIST_B (A, B). How do I implement this in SQL Server 2008 R2?
I think it is important (both for us and for you) to know the the purpose for adding the additional foreign key?
Depending on the exact problem you are trying to solve (data validation on entry, cascading deletes, etc) and the flexibility that you have for solving them (ability or inability to alter the data structure), you could implement logical constraints through triggers. We use this approach at times when we just need to catch edge conditions that should rarely, if ever, occur.
If triggers are insufficient for your situation and foreign keys are required, then about the only option that you have left (without redesigning all of the tables) is to store LIST_C.A into LIST_D and then create the FKey back to LIST_B.
The other option is to redesign it such that you have intermediate tables that contain the appropriate links between all of the tables, but it doesn't sound like this is desirable.