Foreign Key constraints in SQL Server - sql-server

I have a database scheme with versioning data rows, e.g.
Table Person has the columns
id (int, PK)
name (String)
current (Bool)
firstid (int)
Current is 0 for previous data, 1 for the latest entry. All rows for the same entity have the same FirstID, which points to the first ID of the set.
Referencing table: Adress with the same principle:
id (int, PK)
street (String)
person_id (int)
current (Bool)
firstid (int)
Person_id points to patient.firstid. So firstid is never unique, only if current=1
My problem is: I would like to add referential integrity to my tables, but this only works, if the referenced column (patient.firstid) is unique...

You should look at refactoring your table structure. But to keep within the current structure, add a self-referencing foreign key to person
firstid references person(id)
Then, reference the "base person" from the address table
address.person_id references person(id) -- which should ONLY store a link to the first id

A FOREIGN KEY constraint does not have
to be linked only to a PRIMARY KEY
constraint in another table; it can
also be defined to reference the
columns of a UNIQUE constraint in
another table. A FOREIGN KEY
constraint can contain null values;
however, if any column of a composite
FOREIGN KEY constraint contains null
values, then verification of the
FOREIGN KEY constraint will be skipped.
Data from two related tables can be combined even if no PRIMARY KEY or FOREIGN KEY constraints are defined between the tables, but a foreign key relationship between two tables indicates that the two tables have been optimized to be combined in a query that uses the keys as its criteria.
reference http://msdn.microsoft.com/en-us/library/aa933117(v=sql.80).aspx

Related

T-SQL inserting data into table with foreign key

I'm using SQL Server 2014 to create and insert data into tables and came along a problem when it comes to populating a table with a foreign key constraint in it. I have a table user and and a table city which were created beforehand.
I used code to alter the user table to include a cityId foreign key from table city with this code:
ALTER TABLE [Schema].[user]
ADD cityId UNIQUEIDENTIFIER NOT NULL
CONSTRAINT usr_cid_fk
FOREIGN KEY (cityId) REFERENCES [Schema].[city] (cityId);
GO
Basically I modified the user table by adding a field called cityId which i made foreign key. now the problem is that when inserting data, in the first line
INSERT INTO [Schema].[user](name, surname, dob, gender, .. )
cityId cannot be found to be mapped. Dunno why it ain't showing. In the design view it is listed as a foreign key so there should be no problems.
Thanks a lot
try :
ALTER TABLE [Schema].[user]
ADD cityId NUMBER NOT NULL
CONSTRAINT usr_cid_fk
FOREIGN KEY (cityId) REFERENCES [Schema].[city] (cityId);
Note :
For ADD cityId UNIQUEIDENTIFIER NOT NULL
By the SQL standard, a foreign key must reference either the primary key or a unique key of the parent table. If the primary key has multiple columns, the foreign key must have the same number and order of columns. Therefore the foreign key references a unique row in the parent table; there can be no duplicates.

how to define relations between many tables while I have multiple columns primary key?

I have one table its name is (DataInfo) that contains data information "this table will be linked to every table in the database"
DataID,DataName
and I have two another tables
first one is :
DataID,CurrencyID,CurrencyName
Second one is :
DataID,TransID,TransDec,TransAmount,CurrencyID
my question is how to define the relations between these tables ?
DataID will be the foreign key for two tables besides "DataInfo". For first table CurrencyID will be the primary key and DataID will be foreign key. For second table TransID will be the primary key and DataID and CurrencyID will be the foreign key. Both table need not have a tuple of columns as their primary key as TransID will be unique for every transaction and so will be CurrencyID for each currency

SQL Server - Foreign Key Referencing Primary Key A OR B

Say I have a table called Matchup that contains two sports teams. I also have a table called Pick that has a column that must match either Team_A OR Team_B. So it's a foreign key of one OR the other columns in Matchup. Is this possible?
Matchup
Team_A
Team_B
Pick
Pick_Team - FK Matchup (Must match Team_A or Team_B from Matchup).
I would split your Matchup table into two: Matchup proper and MatchupDetails.
The Matchup table would have a MatchupID column as its primary key.
The MatchupDetails one would consist of at least two columns: MatchupID to reference the Matchup table and TeamID to reference the Team table (you do have one, don't you?). The two columns would form the table's composite primary key.
Finally, there would be this Pick table. Since you've got multiple users (as per one of your comments), there would need to be a UserID reference. Two more columns, MatchupID & TeamID would serve as a composite foreign key referencing the corresponding column set in MatchupDetails. And to ensure that one user can pick no more than one team from a match-up, a composite primary key of (UserID, MatchupID) should do.
To summarise, here's a complete outline of the relevant part of the schema:
Matchup:
MatchupID
PRIMARY KEY (MatchupID)
MatchupDetails:
MatchupID
TeamID
FOREIGN KEY (MatchupID)
FOREIGN KEY (TeamID)
PRIMARY KEY (MatchupID, TeamID)
Pick:
UserID
MatchupID
TeamID
FOREIGN KEY (UserID)
FOREIGN KEY (MatchupID, TeamID)
PRIMARY KEY (UserID, MatchupID)
I dont think that this is the correct approach.
I would rather recomend that you add an additional field to table Matchup (lets say Pick) and add a CHECK CONSTRAINT to ensure that it is either Team_A or Team_B.
CHECK constraints enforce domain integrity by limiting the values that
are accepted by one or more columns. You can create a CHECK constraint
with any logical (Boolean) expression that returns TRUE or FALSE based
on the logical operators.
From FOREIGN KEY Constraints
In a foreign key reference, a link is created between two tables when
the column or columns that hold the primary key value for one table
are referenced by the column or columns in another table. This column
becomes a foreign key in the second table.
And it does not seem to be what you are looking for.

Postgres: two foreign keys to same primary key field

create table date_dimension (
id serial primary key,
date_id date,
..... others
);
create table temp (
id serial primary key,
from_date integer,
to_date integer,
value integer,
foreign key (from_date, to_date) references date_dimension(id, id)
);
How can I refer both from_date and to_date to id field in date_dimension?
The current code fails to do that saying
ERROR: there is no unique constraint matching given keys for referenced table "date_dimension"
Thank you
each FOREIGN KEY constraint added to a table will always relate one row in the referencing table to one row* in the referant. If you want to have each row in the referencing to refer to two distinct rows in the referant, you need two, separate foreign key constraints.
you want:
foreign key (from_date) references date_dimension(id)
foreign key (to_date) references date_dimension(id)
You almost always want to have exactly the rows in the foreign key to be the same as the primary key in the referant.
* Actually, there may be more than one row in the referant if the foreign key is smaller than a candidate key of the referant. this is seldom useful, though, and almost certainly unrelated to the problem you're describing

Are foreign keys indexed automatically in SQL Server?

Would the following SQL statement automatically create an index on Table1.Table1Column, or must one be explicitly created?
Database engine is SQL Server 2000
CREATE TABLE [Table1] (
. . .
CONSTRAINT [FK_Table1_Table2] FOREIGN KEY
(
[Table1Column]
) REFERENCES [Table2] (
[Table2ID]
)
)
SQL Server will not automatically create an index on a foreign key. Also from MSDN:
A FOREIGN KEY constraint does not have
to be linked only to a PRIMARY KEY
constraint in another table; it can
also be defined to reference the
columns of a UNIQUE constraint in
another table. A FOREIGN KEY
constraint can contain null values;
however, if any column of a composite
FOREIGN KEY constraint contains null
values, verification of all values
that make up the FOREIGN KEY
constraint is skipped. To make sure
that all values of a composite FOREIGN
KEY constraint are verified, specify
NOT NULL on all the participating
columns.
As I read Mike's question, He is asking whether the FK Constraint will create an index on the FK column in the Table the FK is in (Table1). The answer is no, and generally. (for the purposes of the constraint), there is no need to do this The column(s) defined as the "TARGET" of the constraint, on the other hand, must be a unique index in the referenced table, either a Primary Key or an alternate key. (unique index) or the Create Constraint statment will fail.
(EDIT: Added to explicitly deal with comment below -)
Specifically, when providing the data consistency that a Foreign Key Constraint is there for. an index can affect performance of a DRI Constraint only for deletes of a Row or rows on the FK side. When using the constraint, during a insert or update the processor knows the FK value, and must check for the existence of a row in the referenced table on the PK Side. There is already an index there. When deleting a row on the PK side, it must verify that there are no rows on the FK side. An index can be marginally helpful in this case. But this is not a common scenario.
Other than that, in certain types of queries, however, where the query processor needs to find the records on the many side of a join which uses that foreign key column. join performance is increased when an index exists on that foreign key. But this condition is peculiar to the use of the FK column in a join query, not to existence of the foreign Key constraint... It doesn't matter whether the other side of the join is a PK or just some other arbitrary column. Also, if you need to filter, or order the results of a query based on that FK column, an index will help... Again, this has nothing to do with the Foreign Key constraint on that column.
No, creating a foreign key on a column does not automatically create an index on that column. Failing to index a foreign key column will cause a table scan in each of the following situations:
Each time a record is deleted from the referenced (parent) table.
Each time the two tables are joined on the foreign key.
Each time the FK column is updated.
In this example schema:
CREATE TABLE MasterOrder (
MasterOrderID INT PRIMARY KEY)
CREATE TABLE OrderDetail(
OrderDetailID INT,
MasterOrderID INT FOREIGN KEY REFERENCES MasterOrder(MasterOrderID)
)
OrderDetail will be scanned each time a record is deleted in the MasterOrder table. The entire OrderDetail table will also be scanned each time you join OrderMaster and OrderDetail.
SELECT ..
FROM
MasterOrder ord
LEFT JOIN OrderDetail det
ON det.MasterOrderID = ord.MasterOrderID
WHERE ord.OrderMasterID = #OrderMasterID
In general not indexing a foreign key is much more the exception than the rule.
A case for not indexing a foreign key is where it would never be utilized. This would make the server's overhead of maintaining it unnecessary. Type tables may fall into this category from time to time, an example might be:
CREATE TABLE CarType (
CarTypeID INT PRIMARY KEY,
CarTypeName VARCHAR(25)
)
INSERT CarType .. VALUES(1,'SEDAN')
INSERT CarType .. VALUES(2,'COUP')
INSERT CarType .. VALUES(3,'CONVERTABLE')
CREATE TABLE CarInventory (
CarInventoryID INT,
CarTypeID INT FOREIGN KEY REFERENCES CarType(CarTypeID)
)
Making the general assumption that the CarType.CarTypeID field is never going to be updated and deleting records would be almost never, the server overhead of maintaing an index on CarInventory.CarTypeID would be unnecessary if CarInventory was never searched by CarTypeID.
According to: https://learn.microsoft.com/en-us/sql/relational-databases/tables/primary-and-foreign-key-constraints?view=sql-server-ver16#indexes-on-foreign-key-constraints
Unlike primary key constraints, creating a foreign key constraint does not automatically create a corresponding index

Resources