Understanding Update and Delete Rules for Relationships in SSMS 2008 - sql

I am confused about what means the update and delete rule in SQL Server 2008 Management Studio when we define foreign key constraints. I also did not find related help documents (e.g. F1 help).
Here is the screen snapshot. Appreciate if anyone could describe what do they mean and recommend some related documents to read. :-)

The foreign key defines a parent - child relationship between two tables. The primary key in the parent table is the foreign key in the up to n child table rows.
Now if that primary key in the parent table gets UPDATE, the UPDATE RULE kicks in. Either all the child rows are also updated, set to NULL or whatever. Best practice however is to have a primary key that NEVER changes (a fixed ID or something), so that's the less important rule.
The more important one is the DELETE rule - what if the parent row is deleted (e.g. the Order is deleted)? You can either also delete all child rows (all the Order line items) with CASCADE DELETE, or you can set their foreign key to NULL (they don't have a parent anymore) - that's totally up to your concrete scenario.
In the Order/order lines scenario, it might be totally useful to delete the order lines when the complete order gets deleted, but you probably don't want to delete a product, just because an order that references it has been deleted - there's no one single CORRECT answer - it depends on your scenario and your app.
Marc

It looks like the documentation is at Foreign Key Relationships Dialog Box.
BTW, F1 help worked fine for me in SSMS 2008. It took me right to the above page (after I searched for 1/2 hour online, of course).

A foreign key field can only store null or a value defined by the primary key field.
If you try to change the foreign key value to something not defined by a primary key you will get an error. Likewise if you try to change a primary key which has foreign key dependencies you will get an error... as an example
Models table
modelID (primary key) model
1 Jeep
2 Ford
Customer table
id customer modelID (foreign key of Models.modelID)
1 1234 1
2 2345 2
If you try to delete the Jeep record from Models you will get an error because customer 1234 has a modelID set to 1, and this if the foreign key. Likewise if I try to update customer 1234 to have a modelID of 3 it will throw an error because there is no primary key in the Models table having a value of 3
Check this out

Related

Swap two values in an indexed field

Is there a simple way (using a SQL query or VBA with a DAO recordset) to swap two values in an indexed field? In my case said field is the primary key of a small table (not expected to exceed 30 records). Expected input and output below.
Before:
StageNumber | Description
------------+--------------------------
01 | First Thing
02 | Second Thing
After:
StageNumber | Description
------------+--------------------------
02 | First Thing
01 | Second Thing
I'm aware this looks like I could simply switch the descriptions rather than the StageNumber but the StageNumber is used as a foreign key into another table with cascading updates specified in the relationship so simply switching the description would cause 'child' records to be associated with the wrong 'parent'.
Ideally this would be achieved with a single UPDATE..SET query but for the life of me I can't figure out what the syntax for such an operation would be without causing a primary key violation error.
This highlights one of the perils of using a Natural Keys as a primary key, when there is a risk of change of identity.
Assuming there might be similar changes in future, an alternative is to add a new Surrogate PK to the Stage table (e.g. ID as an integer AUTONUMBER), and then:
Add a new StageId foreign key column to all tables referencing Stage.
Then update the StageId column to assign the correct StageId via a lookup join via the existing foreign key (StageNo)
Then drop the FOREIGN KEY constraint on the existing StageNumber foreign key columns in the referencing tables.
Drop the PRIMARY KEY on Stage.StageNumber and change the PK to Stage.Id
Then re-add the FOREIGN KEY constraint on the new StageId foreign key columns in the referencing tables.
You are now free to change the value of the StageNumber column as it is no longer part of a foreign key.
Update StageNumber of the first record to an arbitrary number not in use.
Update StageNumber of the second record to that the first record had.
Update StageNumber of the first record to that the second records had.
Or, in two steps:
Update both StageNumbers to arbitrary numbers not in use.
Update both StageNumbers to that the other record had.

When should foreign keys be used? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm just starting to learn SQL (using SQLite) and I'm trying to figure out when foreign keys should be used. The way it was explained to me, was that foreign keys should be used any time repeated data comes up and just save IDs to save space. The database I'm making has a few thousand records in it, with categories and counties listed (probably a few dozen uniques in each column). So I can make a separate table for counties with county name and a primary key id, and do the same thing with categories. And I have no doubt that it would make the database about 5% smaller. But is that the only benefit? It seems like it's making everything else more complex. Adding in IDs for counties and categories which wouldn't otherwise be needed. When looking at the table in phpLiteAdmin, it just shows you a number instead of the category/county name, making it more difficult to visualize. What are the advantages of using foreign keys and making separate tables in this situation? Or should I just not do that and stick with all the data (repetition and all) in one table? Also- would it make sense at all to make the counties/categories tables just one column with no numeric primary key, since they'll all be uniques anyway? That would at least show the full names in phpLiteAdmin. Thanks in advance!
If you are using foreign key. its also called as referential integrity.
Suppose you have two table first table is account_user and second is account_user_detail.
so account_user table will have primary key of account_number of account_id. and account_user_detail table will have accounts holder address detail.
so if you are relating both the tables then account_number or account_id will be same.
so using value of primary key in second table we define foreign key.
foreign key identifies that value of account_number in second table is reference of Mr. Xyz in first table with same account number.
So Foreign key is used for joining two table with a column that is common to both tables and share same unique value.
You may check this:
SQL foreign key constraints are used to enforce "exists" relationships
between tables.
EDIT:-
The foreign key constraints exist is to guarantee that the referenced rows exist.
Also the wiki says:-
One important part of database design is making sure that
relationships between real-world entities are reflected in the
database by references, using foreign keys to refer from one table to
another.[9] Another important part of database design is database
normalization, in which tables are broken apart and foreign keys make
it possible for them to be reconstructed.
Also check this Thread.
Why are foreign keys more used in theory than in practice?
If your country name is "United States of America" this is 24bytes. If you use a foriegn key you will need only 2-4 bytes. Thats a huge difference.
When you are searching for a country name it is going to be very fast because you only have to match a number and not the whole string.
Also if you use an index on the country_id field it is going to much smaller.
I can understand you point about the added complexity. In your case you can get away with not using foreign keys but you shouldn't. You will eventually need them so better be prepared and experienced on the subject.
But is that the only benefit?
No.
Foreign keys are logically similar to pointers or references in most programming languages. Imagine trying to make some data structure by just copying data, without being able to reference anything. A database without foreign keys would be similarly problematic.
Without the ability to reference things, you'd have to make sure all the copies are kept up-to date. If there is a bug that leads to one copy being updated but not the other, that would effectively corrupt the data - you'd no longer know which copy is correct.
Avoiding redundancies is not primarily about space, it's about data integrity. The whole purpose of database normalization (which couldn't be done without foreign keys) is the avoidance of redundancies and therefore the protection the data integrity.
In your particular case...
Should a category (or country) be able to exist without being connected to any row from the main table?
Is there any data that should exist for a category, independently from which rows in the main table this category is connected to?
Is there any operation (like rename) that should be done independently?
If either answer is "yes", you should put categories into a separate lookup table. Whether this lookup table should use natural (name) or surrogate (ID) key is a different issue. Some pros and cons are listed here.
Foreign key constraints are used to restrict the values that are allowed to exist in a column or set of columns. For example, take marriages:
CREATE TABLE person
(person_id INTEGER NOT NULL PRIMARY KEY
, name varchar NOT NULL
);
CREATE TABLE marriage
( person1 INTEGER NOT NULL PRIMARY KEY
, person2 INTEGER NOT NULL UNIQUE
, comment varchar
, CONSTRAINT marriage_1 FOREIGN KEY (person1) REFERENCES person(person_id)
, CONSTRAINT marriage_2 FOREIGN KEY (person2) REFERENCES person(person_id)
, CONSTRAINT order_in_court CHECK (person1 < person2)
);
-- add some data ...
INSERT INTO person(person_id,name) values (1,'Bob'),(2,'Alice'),(3,'Charles');
INSERT INTO marriage(person1,person2, comment) VALUES(1,2, 'Crypto marriage!') ; -- Ok
INSERT INTO marriage(person1,person2, comment) VALUES(2,1, 'Not twice!' ) ; -- Should fail
INSERT INTO marriage(person1,person2, comment) VALUES(3,3, 'No you dont...' ) ; -- Should fail
INSERT INTO marriage(person1,person2, comment) VALUES(2,3, 'OMG she did it again.' ) ; -- Should fail (does not)
INSERT INTO marriage(person1,person2, comment) VALUES(3,4, 'Non existant persons are not allowed to marry !' ) ; -- Should fail
SELECT p1.name, p2.name, m.comment
FROM marriage m
JOIN person p1 ON m.person1 = p1.person_id
JOIN person p2 ON m.person2 = p2.person_id
;
The above DDL tries to model marriages (and partly fails) The constraints to be modelled are:
only existing persons can be married
marriages can only exist between two different persons
A person can only be married once
The output:
INSERT 0 3
INSERT 0 1
ERROR: new row for relation "marriage" violates check constraint "order_in_court"
ERROR: new row for relation "marriage" violates check constraint "order_in_court"
INSERT 0 1
ERROR: insert or update on table "marriage" violates foreign key constraint "marriage_2"
DETAIL: Key (person2)=(4) is not present in table "person".
name | name | comment
-------+---------+-----------------------
Bob | Alice | Crypto marriage!
Alice | Charles | OMG she did it again.
(2 rows)

ON UPDATE CASCADE with two columns in a single table in SQL Server [duplicate]

I have a database table called Lesson:
columns: [LessonID, LessonNumber, Description] ...plus some other columns
I have another table called Lesson_ScoreBasedSelection:
columns: [LessonID,NextLessonID_1,NextLessonID_2,NextLessonID_3]
When a lesson is completed, its LessonID is looked up in the Lesson_ScoreBasedSelection table to get the three possible next lessons, each of which are associated with a particular range of scores. If the score was 0-33, the LessonID stored in NextLessonID_1 would be used. If the score was 34-66, the LessonID stored in NextLessonID_2 would be used, and so on.
I want to constrain all the columns in the Lesson_ScoreBasedSelection table with foreign keys referencing the LessonID column in the lesson table, since every value in the Lesson_ScoreBasedSelection table must have an entry in the LessonID column of the Lesson table. I also want cascade updates turned on, so that if a LessonID changes in the Lesson table, all references to it in the Lesson_ScoreBasedSelection table get updated.
This particular cascade update seems like a very straightforward, one-way update, but when I try to apply a foreign key constraint to each field in the Lesson_ScoreBasedSelection table referencing the LessonID field in the Lesson table, I get the error:
Introducing FOREIGN KEY constraint 'c_name' on table 'Lesson_ScoreBasedSelection' may cause cycles or multiple cascade paths.
Can anyone explain why I'm getting this error or how I can achieve the constraints and cascading updating I described?
You can't have more than one cascading RI link to a single table in any given linked table. Microsoft explains this:
You receive this error message because
in SQL Server, a table cannot appear
more than one time in a list of all
the cascading referential actions that
are started by either a DELETE or an
UPDATE statement. For example, the
tree of cascading referential actions
must only have one path to a
particular table on the cascading
referential actions tree.
Given the SQL Server constraint on this, why don't you solve this problem by creating a table with SelectionID (PK), LessonID, Next_LessonID, QualifyingScore as the columns. Use a constraint to ensure LessonID and QualifyingScore are unique.
In the QualifyingScore column, I'd use a tinyint, and make it 0, 1, or 2. That, or you could do a QualifyingMinScore and QualifyingMaxScore column so you could say,
SELECT * FROM NextLesson
WHERE LessonID = #MyLesson
AND QualifyingMinScore <= #MyScore
AND #MyScore <= QualifyingMaxScore
Cheers,
Eric

SQL Server 2008: The columns in table do not match an existing primary key or unique constraint

I need to make some changes to a SQL Server 2008 database.
This requires the creation of a new table, and inserting a foreign key in the new table that references the Primary key of an already existing table. So I want to set up a relationship between my new tblTwo, which references the primary key of tblOne.
However when I tried to do this (through SQL Server Management Studio) I got the following error:
The columns in table 'tblOne' do not
match an existing primary key or
UNIQUE constraint
I'm not really sure what this means, and I was wondering if there was any way around it?
It means that the primary key in tblOne hasn't been properly declared - you need to go to tblOne and add the PRIMARY KEY constraint back onto it.
If you're sure that tblOne does have a PRIMARY KEY constraint, then maybe there are multiple tblOne tables in your DB, belonging to different schemas, and your references clause in your FK constraint is picking the wrong one.
If there's a composite key (which your comment would indicate), then you have to include both columns in your foreign key reference also. Note that a table can't have multiple primary keys - but if it has a composite key, you'll see a key symbol next to each column that is part of the primary key.
If you have a composite key the order is important when creating a FK, and sometimes the order is not how it is displayed.
What I do is go to the Keys section of the table1 and select script primary key as create to clipboard and then create FK using the order as shown in script
I've had this situation that led me to this topic. Same error but another cause. Maybe it will help someone.
Table1
ColA (PK)
ColB (PK)
ColC
Table2
ID (PK)
ColA
COLB
When trying to create foreign key in Table2 I've choose values from combobox in reverse order
Table1.ColB = Table2.ColB
Table1.ColA = Table2.ColA
This was throwing me an error like in topic name. Creating FK keeping order of columns in Primary key table as they are, made error disappear.
Stupid, but.. :)
If you still get that error after you have followed all advice from the above answers and everything looks right.
One way to fix it is by Removing your Primary keys for both tables, Save, Refresh, and add them again.
Then try to add your relationship again.
This Error happened with me When I tried to add foreign key constraint starting from PrimaryKey Table
Simpy go to other table and and create this foreign key constraint from there (foreign key Table)
This issue caught me out, I was adding the relationship on the wrong table. So if you're trying to add a relationship in table A to table B, try adding the relationship in table B to table A.
That looks like you are trying to create a foreign key in tblTwo that does not match (or participate) with any primary key or unique index in tblOne.
Check this link on MSDN regarding it. Here you have another link with a practical case.
EDIT:
Answwering to your comment, I understand you mean there are 2 fields in the primary key (which makes it a composite). In SQL it is not possible to have 2 primary keys on the same table.
IMHO, a foreign key field should always refer to a single register in the referenced table (i.e. the whole primary key in your case). That means you need to put both fields of the tblOne primary key in tblTwo before creating the foreign key.
Anyway, I have investigated a bit over the Internet and it seems SQL Server 2008 (as some prior versions and other RDBMS) gives you the possibility to reference only part of the primary key as long as this part is a candidate key (Not Null and Unique) and you create an unique constraint on it.
I am not sure you can use that in your case, but check this link for more information on it.
I have found that the column names must match.
Example:
So if tblOne has id called categoryId a reference in tblTwo must also be called categoryId.
_tblname, primary key name, foreign key_
tblOne, "categoryId", none
tblTwo, "exampleId", "categoryId"
I noticed this when trying to create foreign key between 2 tables that both had the column name "id" as primary key.
If nothing helps, then this could be the reason:
Considering this case:
Table A:
Column 1 (Primary Key)
Column 2 (Primary Key)
Column 3
Column 4
Table B:
Column a (Primary Key)
Column b
Column c
when you are defining a dependency B to A, then you are forced to respect the order in which the primaries are defined.
That's mean your dependency should look like this:
Table A Table B
Column 1 Column b
Column 2 Column c
AND NOT:
Table A Table B
Column 2 Column c
Column 1 Column b
then this will lead to the error you are encountering.
I've found another way to get this error. This can also happen if you are trying to make a recursive foreign key (a foreign key to the primary key in the same table) in design view in SQL Management Studio. If you haven't yet saved the table with the primary key it will return this message. Simply save the table then it will allow you to create the foreign key.
If you have data in your tables this could be the issue.
In my case I had some data in the Account table that I loaded at 3 pm, and some data in Contact table that I loaded at 3:10 pm, so Contact table had some values that weren't in my Account table yet.
I ended up deleting these values from the contact table and then managed to add a key without any problems.
Kindly also see that there are no existing data inside the table where the primary key is defined while setting the foreign key with another table column.
this was the cause of the error in my case.
I had to take backup empty the table set the relationship and then upload the data back.
sharing my experience
Was using ms sql smss

Database table id-key Null value and referential integrity

I'm learning databases, using SQLce. Got some problems, with this error:
A foreign key value cannot be inserted because a corresponding primary key value does not exist.
How does the integrity and acceptance of data work when attempting to save a data row that does not have specified one foreign key. Isn't it possible to set it to NULL in some way, meaning it will not reference the other table? In case, how would I do that? (For an integer key field)
Also, what if you save a row with a valid foreign key that corresponds to an existing primary key in other table. But then decide to delete that entry in this other table. So the foreign key will no longer be valid. Will I be allowed to delete? How does it work? I would think it should then be simply reset to a null value.. But maybe it's not that simple?
What you need to do is insert your data starting from the parent down.
So if you have an orders table and an items table that refers to orders, you have to create the new order first before adding all the children to the list.
Many of the data access libraries that you can get (in C# there is Linq to SQL) which will try and abstract this problem.
If you need to delete data you actually have to go the other way, delete the items before you delete the parent order record.
Of course, this assumes you are enforcing the foreign key, it is possible to not enforce the key, which might be useful during a bulk delete.
This is because of "bad data" you have in the tables. Check if you have all corresponding values in the primary table.
DBMS checks the referential integrity for ensuring the "correctness" of data within database.
For example, if you have a column called some_id in TableA with values 1 through 10 and a column called some_id in TableB with values 1 through 11 then TableA has no corresponding value (11) for that which you have already in TableB.
You can make a foreign key nullable but I don't recommend it. There are too many problems and inconsistencies that can arise. Redesign your tables so that you don't need to populate the foreign key for values that don't exist. Usually you can do that by moving the column to a new table for example.