SQL Server table PK and FK - sql-server

I am creating a relationship between 2 tables:
The relationship I like to form is between the Inventory an InventoryExtended tables.
The primary key for the Inventory table is InvID (Inventory ID).
The reason why I created the InventoryExtended is becauses only 1% of the inventory items in the Inventory table will need additional or extended fields, the rest will not.
Instead of adding these additional fields in the Inventory table where 99% will be blank for 50 additional fields that I need I decided to create an InventoryExtended table and store the 50 fields there.
The relationship between the Inventory an InventoryExtended table will be 1 to 1.
Meaning, for the 1% of the records in the Inventory table , the InvId will be the same as the InvId in the InventoryExtended table.
My question is that should the InvID in the InventoryExtended table be a FK (Foreign Key) or should it be a PK and a FK?
I am thinking it should be a PK and a FK as there the InvID will be unique in the InventoryExtended table.
Thanks in advance.

You are correct.
The InvID should be a PRIMARY KEY and a FOREIGN KEY as it will be unique in the InventoryExtended table.
This type of relationship is indeed 1:1 or (more accurately) 1::0..1, as only some of the rows in the Inventory table will have a related row in InventoryExtended.
Also note that the InventoryExtended (InvID) should not have the IDENTITY property, even if the Inventory (InvID) has it.

The InvID will be both a PK and FK for the extended table.
If you know in advance (meaning when you attempt to fetch data) whether or not a particular inventory type will have the extended data, for such records you can even skip the original table altogether and simply use two disjoint tables smallInventory and bigInventory such that no records of one are present in the other.

Related

Creating a foreign key against a composite key in MS SQL Server

I'm trying to create a foreign key between two tables. Problem is one of those tables has a composite primary key..
My tables are products (one row per product) and product_price_history (many rows per product).
I have a composite key in product_price_history, which is product id and start date of a specific price for that product.
Here's my code :
CREATE TABLE products (
product_id INT IDENTITY(1,1) PRIMARY KEY,
product_name VARCHAR(50) NOT NULL,
product_desc VARCHAR(255) NULL,
product_group_id INT
)
CREATE TABLE product_price_history (
product_id INT NOT NULL,
start_date DATE NOT NULL,
end_date DATE NULL,
price NUMERIC (6,2) NOT NULL
)
ALTER TABLE product_price_history
ADD CONSTRAINT pk_product_id_start_dt
PRIMARY KEY (product_id,start_date)
Now I'm trying to create a foreign key between the products table and the product_price_history table but I can't because its a composite key.
Also it doesn't make sense to add the start date (the other part of the foreign key) to the products table.
What's the best way to deal with this? Can I create a foreign key between these tables? Do I even NEED a foreign key?
My intentions here are
to enforce uniqueness of the product price information. A product can only have one price at any time.
to link these two tables so there's a logical join between them, and I can show this in a database diagram
The foreign key on the product_price_history table should only include product_id. Your target is to ensure that any entry product_price_history already has "parent" entry in products. That has nothing to do with start_date.
The way I see this situation, in theory, fully normalized version of the tables would have to have current_price as unique value in products table. And the product_price_history is simply a log table.
It's not necessary to do it this way, with a physical field, but thinking from this perspective helps to see where your tables model is slightly de-normalized.
Also, if you make product_price_history table anything but simple log table, how do you ensure that new start_date is newer than previous end_date? You can't even express that as a primary key. What if you edit start_date later? I would even think to create different compaund key for product_price_history table. Perhaps product_id+insert_date or only auto-increment id, while still keeping foreign key relationship to the products.product_id.

Handling multi-select list in database design

I'm creating a clinic management system where I need to store Medical History for a patient. The user can select multiple history conditions for a single patient, however, each clinic has its own fixed set of Medical History fields.
For example:
Clinic 1:
DiseaseOne
DiseaseTwo
DiseaseThree
Clinic 2:
DiseaseFour
DiseaseFive
DiseaseSize
For my Patient visit in a specific Clinic , the user should be able to check 1 or more Diseases for the patient's medical history based on the clinic type.
I thought of two ways of storing the Medical History data:
First Option:
Add the fields to the corresponding clinic Patient Visit Record:
PatientClinic1VisitRecord:
PatientClinic1VisitRecordId
VisitDate
MedHist_DiseaseOne
MedHist_DiseaseTwo
MedHist_DisearThree
And fill up each MedHist field with the value "True/False" based on the user input.
Second Option:
Have a single MedicalHistory Table that holds all Clinics Medical History detail as well as another table to hold the Patient's medical history in its corresponding visit.
MedicalHistory
ClinicId
MedicalHistoryFieldId
MedicalHistoryFieldName
MedicalHistoryPatientClinicVisit
VisitId
MedicalHistoryFieldId
MedicalHistoryFieldValue
I'm not sure if these approaches are good practices, is a third approach that could be better to use ?
If you only interested on the diseases the person had, then storing the false / non-existing diseases is quite pointless. Not really knowing all the details doesn't help getting the best solution, but I would probably create something like this:
Person:
PersonID
Name
Address
Clinic:
ClinicID
Name
Address
Disease:
DiseaseID
Name
MedicalHistory:
HistoryID (identity, primary key)
PersonID
ClinicID
VisitDate (either date or datetime2 field depending what you need)
DiseaseID
Details, Notes etc
I created this table because my assumption was that people have most likely only 1 disease on 1 visit, so in case there's sometimes several, more rows can be added, instead of creating separate table for the visit, which makes queries most complex.
If you need to track also situation where a disease was checked but result was negative, then new status field is needed for the history table.
If you need to limit which diseases can be entered by which clinic, you'll need separate table for that too.
Create a set of relational tables to get a robust and flexible system, enabling the clinics to add an arbitrary number of diseases, patients, and visits. Also, constructing queries for various group-by criteria will become easier for you.
Build a set of 4 tables plus a Many-to-Many (M2M) "linking" table as given below. The first 3 tables will be less-frequently updated tables. On each visit of a patient to a clinic, add 1 row to the [Visits] table, containing the full detail of the visit EXCEPT disease information. Add 1 row to the M2M [MedicalHistory] table for EACH disease for which the patient will be consulting on that visit.
On a side note - consider using Table-Valued Parameters for passing a number of rows (1 row per disease being consulted) from your front-end program to the SQL Server stored procedure.
Table [Clinics]
ClinicId Primary Key
ClinicName
-more columns -
Table [Diseases]
DiseaseId Primary Key
ClinicId Foreign Key into the [Clinics] table
DiseaseName
- more columns -
Table [Patients]
PatientId Primary Key
ClinicId Foreign Key into the [Clinics] table
PatientName
-more columns -
Table [Visits]
VisitId Primary Key
VisitDate
DoctorId Foreign Key into another table called [Doctor]
BillingAmount
- more columns -
And finally the M2M table: [MedicalHistory]. (Important - All the FK fields should be combined together to form the PK of this table.)
ClinicId Foreign Key into the [Clinics] table
DiseaseId Foreign Key into the [Diseases] table
PatientId Foreign Key into the [Patients] table
VisitId Foreign Key into the [Visits] table

Relational database one to many relation

I am using Access to create a database. I have two tables with the following data.
Car
CarID - PK
CarName
CarPrice
CustomerID
Customers
CustomerID -PK
Username
Password
CarID
I wish to have the relationship as many cars to one customer. Would I need a 3rd 'link' table or is there a way to do this without another table? Sorry for such a simple question
Remove CarID from your Customer table. Make CustomerID in the Car table a foreign key to Customer, and remove any existing unique constraints on that column.
Remove CarID from your customers table and you would be set. Just be sure to have the CustomerID field in the Car table be a Foreign Key.

Change ID of row and reflect this change to all related tables

Old version
I have a Person table and the table Company.
both tables have a column Id (Identity)
Table Company have Ids of 1 to 165
In the table Person have Ids 1 until 2029
New Version
In the new version of the system, was created a table Entity.
This table contains the records of the Companies and People
The Company and Person tables will be maintained, referring to the Entity table.
The Id in table Entity will be the same in Company or Person table
Question
Both tables have multiple relationships with other tables.
Table Entity (as well as others) has a column ID (identity).
The problem is that the Id were repeated when the two tables together (It was to be expected).
How to import without losing relationships?
Attempts
I thought of changing the value of Ids in Company table, starts from 2030.
Thus the Ids would not duplicate when joining the two tables.
But this creates another questions.
How to do this without losing existing relationships?
How to change the Id of a row in the table and this is reflected in all tables which it relates?
I would like to do this using only DDL (SQL Server)
I thought of changing the value of Ids in Company table, starts from 2030. Thus the Ids would not duplicate when joining the two tables.
Create foreign key constraints on the Person table to all related tables (or alter the existing foreign key constraints) with ON UPDATE CASCADE. Then update the Person table and change the values if the id columns - these changes will cascade to the related tables.
To stop further problems, maybe change the identity columns in Person and Company to something like identity( 1000, 3 ) and identity (1001, 3) respectively.
However, I think the best idea is to have a different EntityID column in the Entity table, unrelated to PersonID and CompanyID. The Entity table would also have a column called AltEntityID or BusinessKey that contains the id from the other table and that does not have a unique constraint or a foreign key constraint.
And if you make small modification to your attempt - add new column, say newId, to Company and to Person to manage relation with Entity and leave id columns as is. Why this is the simpliest way? Because new columns shouldnot be identity columns, from one side. From the other side, you can leave all logic of relating other tables with Company and Person intact.

SQL server constraint - unique key or index?

I have a table that contains all products. There are 3 distinct types of products so these have their own tables, lets say ProductType1, ProductType2, ProductType3.
There is a 1-1 relationship between Products and ProductType(n) on ProductId, but to further constraint the child tables there is an additional relationship using a ProductId, ProductTypeId in Products, and a ProductId, ComputedProductTypeId in each of the other tables.
This ensures that a product can only be added to a single matching ProductType table.
The question is this. As there is already a relationship between the 2 tables on ProductId, rather than using an index for the FK, can I get away with a unique key to constrain the relationship, or will this cause performance issues?
Products
PK ProductId
FK ProductId, ProductTypeId
^
*Add an index for this or unique key constraint?*
ProductType(n)
PK ProductId
FK ProductID, ComputedProductTypeId (fixed int)
Creating an index will be better approach.
If you want to delete entries from your master table, SQL server looks for FK relations if any exists. So Creating Index on your composite key (which includes FK) will speed up the process.

Resources