non identifying relationship in non key attribute - sql-server

I wish to define a relationship between a parent->child table.
The field in the parent table is a non key attribute(relation_field_A). I would like to define a relationship between the parent table and the child table via the relation_field_A field. I want to ensure that a value in Table_B.relation_field_A exists in the Table_A.relation_field_A.
What I want is a non-identifying relationship between the parent and child table. Is this possible?
Table_A
------
Key_A - PK
field1
feild2
relation_field_A
Table_B
-------
Key_B - PK
field1
field2
relation_field_A

If you want to make a foreign key from Table_B to Table_A, then the column in Table_A must have at least an unique index
create unique nonclustered index UX_TableA on table_A (relation_field_A)
See this example
Without this, you would allow a child to have a link to more than one parent, which is not allowed. In a master-child relationship a parent can have 0, 1 or many childs, and a child can have only one parent.
If that is not what you want than you maybe are after a many to many relation ship ?
For that you need a third table which links both together.
There are many examples on google about many-to-many relationships
And if you really just want to ensure that the relation-field-a in Table_B exists in Table_A without an unique index than you cannot achieve this with a foreign key, you could write a trigger on both tables to try to ensure this.
But honestly, it seems like a design flaw has been made somewhere here.

Related

How to use foreign key in two tables based on a flag column?

I have a parent table Tree and two child tables Post and Department.
Based on the Flag column this relation must be set.
How can I do this?
You cannot do that with foreign keys. You could implement a trigger which would check for the ReferenceID presence either on the Post or on the Department table based oh the Flag column.
Although the best approach would be to change your design to have 2 nullable columns as follows, and ensuring only one of them has a value:
CREATE TABLE Tree (
ID Integer NOT NULL,
PostID Integer REFERENCES Post(ID),
DepartmentID Integer REFERENCES Department(ID),
Flag INTEGER NOT NULL
)

How to add MSSQL constraint to limit the number of related tables

I have a parent table with a relationship to each of four child tables. The primary key of the parent table forms both the primary and foreign key for the child tables. For any given row in the parent table, there can only be two child tables associated, either GradeOneA and GradeOneB or GradeTwoA and GradeTwoB. How can I add a constraint that if an ID in the parent table matches an ID in the GradeOneA table then it cannot also match an ID in the GradeTwoA table and vice versa?
You can do this with a CHECK constraint that calls a function on each of the child tables. The function checks the other child tables to see how many of them have the same PK/FK. The constraint looks at the return value and decides whether the row should be allowed.

Refactoring database tables to have a common "base" table

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.

foreign key data deletion should display error for primary key

i have two tables Table1 and Table2. Where table1 column primary key is referred to table2 column as foreign key.
Now i have to display a error message of constraint violation when ever i delete records from table2 which is having foreign key column of table1.
If I get it right your column A (say) in table 1 references column B (say) in table 2.
What you can do is set the ON DELETE to NO ACTION which will prevent deletion of records from table 2 if any children of it still exists in table 1.
You can can do this by:
ALTER TABLE TABLE1 ADD FOREIGN KEY (A) REFERENCES TABLE2 (B) ON DELETE NO ACTION;
You don't have a constraint violation if you delete records from the child table and not the parent. It is normal to delete child records. For instance if I have a user table and a photos tables that contains the userid from the users table, why would I want to stop that action and throw an error if I want to delete a photo? Deleting a child record doesn't also delete the parent.
If you really want to do that, then you must do it through a trigger (make sure to handle multiple record deletes) or if the FK is a required field, then simply don't grant permissions to delete to the table. Be aware that this may mean you can never delete any records even when you try to delete. A simple method may be to not have a delete function available in the application.
I suspect what you really need to a to get a better definition of what is needed in the requirements document. In over 30 years of dealing with hundreds of databases, I have never seen anyone need this functionality.

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