Refactoring database tables to have a common "base" table - sql-server

In my database I have some tables that looks something like:
table1
---------------
id name
table2
---------
id name ParnetId <-This is an ID from Table 1
table3
---------------
id name ParnetId <-This is an ID from Table 2
In the past, It seemed that the three tables are completely separate entities but now (due to a new requested feature...) I need to reference from another table any of the three tables.
Something like:
table4
---------------
id name foreignKey <-This ID should be from Table 1 OR Table 2 OR Table 3
So, I figured I could add a table that will hold the Id's for tables 1-3 and reference it from the table 4 (+ from tables 1-3 for the Id column).
Please note that I am working on a live database that already contains data.
My questions are:
Is there anything I need to watch out while performing the refactoring process?
How would I migrate the existing records id's from tables 1-3 to table 4 (relating to identical id's in the three tables)?
Is there a better strategy you can think of?

A new table (eg. CommonTable) with its own primary key, with nullable fields as foreign keys to table1, table2 and table3 seems like the way to go.
That way table4 can have a single foreign key to CommonTable, which may link to either table1 or table2 or table3.
A second approach would be to create a view (eg. CommonView) over table1, table2 and table3. You would need to concoct a fake primary key for this - perhaps "t1-xxx", "t2-xxx", "t3-xxx" for table1/2/3. I've used this technique as a temporary data migration mechanism, but wouldn't consider it as a long term solution.
A third approach, probably the easiest to implement, is simply to have multiple nullable foreign keys on table4:
table1Id
table2Id
table3Id
I would strongly advise against having a single field which is a foreign key to more than one table. I've seen this in action and it's a nightmare to work with. Think of the future developers confusion.

I would suggest having 7 tables in total table4, table1, table2, table3, t4t1link, t4t2link and t4t3link.
t4tXlink table should contain the primary keys from table4 and tableX. Thus you can have proper constraints in your database.
If you have just 1 table to contain 3 separate foreignkeys you can not have constraint that disallows values from other 2 columns.

Related

Relationships Between 3 Tables in SQL Server

Relationships between Tables
This is a True or Not???
and what is the Key of Table 3 ?
The point is you don't need any relation between Table1 and Table3!
Relations between tables are being used to point to a specific record of data using a primary key (usually an ID), which in this chart you can find that specific record of Table1 using the relation between Table2 and Table3.
I hope this answer helps :)

If I query a column with a foreign key on it do i need to join the referenced table?

Lets say I have a table(table1) that has a column(column1) which has a foreign key on it referencing another table(table2). If all I want is the data in column1 do I need to join table1 and table2? So will the following code be sufficient:
SELECT column1
FROM table1;
Yes, it will be sufficient.
However, unlike what stan wrote in his comment, foreign key constraints are not for joins.
They are the database way of enforcing a part of data integrity called referencial integrity.
The meaning of a foreign key is that the database will not allow for 'orphan' records in the 'child' table - meaning that you can't insert records to the table if the value of the fk column does not exist in the referenced table.
This is also true for updates.
Also, you can't delete a record that has an fk referecing it.
Joins has nothing to do with fk constrains, though they often use the same columns that are used for the fk.You can join every table you want to every other table or view. In fact, some join types doesn't even have a join condition.

Access Relationship Design

I am fairly green when it comes to working with Access and databases in general.
I am asking for your help in figuring out how to set the correct relationships for three tables:
Table 1 contains:
(no unique ID)
SalesTripID
EmployeeName
StartDate
EndDate
*Each record on this table is related to 1 specific employee's 1 specific sales trip
Table 2 contains:
HotelName
HotelStart
HotelEnd
HotelTotal
*This table may contain multiple records that belong to only 1 record on table 1 (for instance, an employee would stay at 2 hotels during their sales trip)
Table 3 contains:
(no unique ID)
MealVendor
MealDate
MealTotal
*This table, similar to Table 2, may have multiple records in it that are tied to the 1 SalesTripID
How do I set something up to show me each SalesTripID, the multiple Table 2, and the multiple Table 3 records associated with it? Do I need to add a Primary Key anything other than Table 1? Is writing a query involved to display the information? Because I am so green, any and all feedback is welcome.
The following is my recommendation:
Add a SalesTripId field on tables 2,3. This is called a ForeignKey.
If SalesTripId in Table1 is not unique (i.e. each employee can have a trip with the same Id as another employee), add another field (Id) in Table1. You can use Access' AutoNumber type for that field.
I recommend always having a primary key in your tables. But you can skip the Id fields in tables 2,3.

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.

Defining a one-to-one relationship in SQL Server

I need to define a one-to-one relationship, and can't seem to find the proper way of doing it in SQL Server.
Why a one-to-one relationship you ask?
I am using WCF as a DAL (Linq) and I have a table containing a BLOB column. The BLOB hardly ever changes and it would be a waste of bandwidth to transfer it across every time a query is made.
I had a look at this solution, and though it seems like a great idea, I can just see Linq having a little hissy fit when trying to implement this approach.
Any ideas?
One-to-one is actually frequently used in super-type/subtype relationship. In the child table, the primary key also serves as the foreign key to the parent table. Here is an example:
CREATE TABLE Organization
(
ID int PRIMARY KEY,
Name varchar(200),
Address varchar(200),
Phone varchar(12)
)
GO
CREATE TABLE Customer
(
ID int PRIMARY KEY,
AccountManager varchar(100)
)
GO
ALTER TABLE Customer
ADD FOREIGN KEY (ID) REFERENCES Organization(ID)
ON DELETE CASCADE
ON UPDATE CASCADE
GO
Why not make the foreign key of each table unique?
there is no such thing as an explicit one-to-one relationship.
But, by the fact that tbl1.id and tbl2.id are primary keys and tbl2.id is a foreign key referenceing tbl1.id, you have created an implicit 1:0..1 relationship.
Put 1:1 related items into the same row in the same table. That's where "relation" in "relational database" comes from - related things go into the same row.
If you want to reduce size of data traveling over the wire consider either projecting only the needed columns:
SELECT c1, c2, c3 FROM t1
or create a view that only projects relevant columns and use that view when needed:
CREATE VIEW V1 AS SELECT c1, c2, c3 FROM t1
SELECT * FROM t1
UPDATE v1 SET c1=5 WHERE c2=7
Note that BLOBs are stored off-row in SQL Server so you are not saving much disk IO by vertically-partitioning your data. If these were non-BLOB columns you may benefit form vertical partitioning as you described because you will do less disk IO to scan the base table.
How about this. Link the primary key in the first table to the primary key in the second table.
Tab1.ID (PK) <-> Tab2.ID (PK)
My problem was I have a 2 stage process with mandatory fields in both. The whole process could be classed as one episode (put in the same table) but there is an initial stage and final stage.
In my opinion, a better solution for not reading the BLOB with the LINQ query would be to create a view on the table that contains all the column except for the BLOB ones.
You can then create an EF entity based on the view.

Resources