Database: One To Many (or One To None) relationship - sql

Im modelling a database in MSSQL 2008.
I have 4 tables.
**User**
userID
userName
**NewsCategory**
newsCategoryID
newsCategoryName
**News**
newsID
newsText
newsCategoryID
**Subscription**
userID
categoryID
I understand that I should have foreign keys between the News and the Category tables. But what should I do with the supscriptions? Should I have a Foreign Key between User and Subscription tables though it's not mandatory to subscribe for something?

Yes you should. Foreign key is used for be sure, that Subscription is created for existing user. Foreign key does not mean, that user should be subscribed on something.

Yes you should have this foreign key because it will prevent a Subscription from existing that does not map to a real user id.
It acts as a constraint on your data.

Subscription is a link (many-many) table and "not mandatory" means there will no row for that user or that user/category.
The foreign key is required to enforce data integrity when you do have subscriptions which will be one or more rows.
Note: In optional parent-child type relationships the FK column(s) will be NULLable to capture "non mandatory". In link tables this is captured by row non-existence

Yes, you should add Foreign keys between User and SubCription tables with Subscription table.
Foreign key contraints are for the validating of adding wrong information to the database. For example, in your Subscription table, there shouldn't be userIDs which are not in the User table and there should be CategoryIDs which are not in the NewsCategory table. These contraints will do the validation for you even if you don't do the validation at the user interface end.

You've gotten some good answers. Let me try to add another.
A SUBSCRIPTION requires both a subscriber and a category. Therefore, each of these columns should not allow nulls. Preventing nulls is not the same thing as a foreign key constraint.
It should also be impossible to insert a row into SUBSCRIPTIONS if the user does not already exist in the USERS table; and it should be impossible to insert a row into SUBSCRIPTIONS if the category does not already exist in the CATEGORIES table. To enforce these rules your SUBSCRIPTIONS table requires two foreign key constraints:
ALTER TABLE SUBSCRIPTIONS ADD CONSTRAINT FK_SUBSCRIPTIONS_USERS FOREIGN KEY(userid) REFERENCES USERS(userid)
ALTER TABLE SUBSCRIPTIONS ADD CONSTRAINT FK_SUBSCRIPTIONS_CATEGORIES FOREIGN KEY(categoryid) REFERENCES CATEGORIES(categoryid)
When you create a foreign key constraint on a table, you are in effect saying to the database engine: make sure that any value that gets inserted into this table already exists in that other table. BTW, a requirement for the constraint to be created is that a unique constraint must be in effect on the column(s) referenced in that table; typically, the referenced column(s) of that table will be the primary key of that table.
By creating a foreign key constraint, you are not saying to the database engine: make sure a row gets inserted into this table. It is quite possible (though it would be unusual) that this table has no rows in it whatsoever. The foreign key constraint simply makes sure that any value that does get inserted into this table has a counterpart in that table.

Related

Check Constraint: Foreign Key type constraint only on first write

I am trying to create a table serving as a log of calculations. Upon entering data, I would like to check if the data entered in some columns exists in another table. In this other table, the data is in fact the primary key, so I could create a FOREIGN KEY constraint - however, I only want the consistency with this "foreign key" to be checked once for each row after newly inserting it, but never again. I do not want to create an actual parent-child relationship of these tables, as the 'child' should keep records regardless of changes to the 'parent'.
I have attempted to implement this using a CHECK constraint, e.g.:
CONSTRAINT CSTR_CALCLOG1 CHECK (USERID in(select USERID from USER_TABLE))
Resulting in the error:
ORA-02251: subquery not allowed here
It seems that check constraints are fairly limited as described here, and therefore not the right tool for the job:
http://www.dba-oracle.com/t_oracle_check_constraint.htm
How can this be achieved?

Does adding a foreign key to a table affect its insertion time?

Is the assumption that each foreign key added a to a table also adds a CHECK constraint that ensures that values inserted in the foreign key column is from the set of values from the table where that key is the primary key.
This would imply that a table with more foreign keys would take longer to insert a value into. Is this correct?
I am using Microsoft SQL Server 2014.
Yes. Foreign key relationships are checked when data is inserted or modified in the table.
The foreign key needs to be to a primary key or unique key. This guarantees that an index is available for the check.
In general, looking up the value in the index should be pretty fast. Faster than the other things that are going on in an insert, such as finding a free page for the data and logging the data.
However, validating the foreign key is going to add some overhead.
Don't mix up foreign keys and checks - there are two different constraint types. For example check accepts nulls and foreign keys not (exception: on delete set null fk option).
When rows are inserted/updated in database set od step is beeing executed, e.g. checking existance of tables, columns, veryfing privileges. Where you have fk database engine must verify contraint before inserting/updateing data to the table - it's additional step to execute.
I have never expirienced situation, when fk painfully slowed down the database operations duration.

How to know when to create a composite constraint?

I am currently learning SQL, and I have a physical data model I need to implement in code. However, during constraint creation, the numbers appearing next to FK and U started confusing me immensely. Consider the diagram. EDIT: Added the full physical model.
I know that when the matter is Primary Keys, we must have a single PK Constraint that's all the columns marked as PK. However, when the thing is FK or Unique constraints, I'm not so sure myself.
Let's assume I want to create the FK constraints for the table Opcao.
Should I create a single constraint for multiple columns, referencing their respective columns like this:
ALTER TABLE MySchema.Opcao ADD CONSTRAINT [FK_SUPERKEY] FOREIGN KEY ([prova], [aluno], [pergunta], [dataRealizacao])
REFERENCES MySchema.Integra([prova], [aluno], [pergunta], [dataRealizacao]);
Or create a constraint for each column, like this:
ALTER TABLE MySchema.Opcao ADD CONSTRAINT [FK_OPCAO_PROVA] FOREIGN KEY ([prova])
REFERENCES MySchema.Integra([prova]);
ALTER TABLE MySchema.Opcao ADD CONSTRAINT [FK_OPCAO_ALUNO] FOREIGN KEY ([aluno])
REFERENCES MySchema.Integra([aluno]);
ALTER TABLE MySchema.Opcao ADD CONSTRAINT [FK_OPCAO_PERGUNTA] FOREIGN KEY ([pergunta])
REFERENCES MySchema.Integra([pergunta]);
ALTER TABLE MySchema.Opcao ADD CONSTRAINT [FK_OPCAO_DATAREALIZACAO] FOREIGN KEY ([dataRealizacao])
REFERENCES MySchema.Integra([dataRealizacao]);
Would the Unique constraints follow the same logic? How do I know when to do one or the other?
You want to make a foreign key consisting of three columns which have to match all the three columns in the referenced table?
Then you should use in my oppinion on constraint for the three columns, because its the semantic you want to tell.
The one constraint for each column approach has the same effect, but you have to think a little to get the intension.
Some other tips: I don't get the semantic of the schema because i don't know the language the entities are named in. It would be easier if they were named in english. One thing i saw is the pergunta column which is duplicated and needs to be consistent in opcao, Integra und Pergunta table, this may lead to problems.
I generally helped me to always make an artifical auto increment primary key for every table (even the join tables for n to m relations), and always reference this artificial key. Then you have less problems (with case insensitivity for example) and the schema is in my oppinion easier to understand.

Are multiple foreign key constraints on the same column "ORed" or "ANDed"

In other words, if I have two foreign key constraints on the same column, will both constraints have to be met or just one in order to successfully add the record?
If you have several constraints defined on a table, then when an operation happens on the table ALL constraints needs to be met. Please note that this applies to ALL types of constraints, not only foreign constraints (that you initially questionned about) :
UNIQUE
NOT NULL
CHECK
FOREIGN KEY
See the sqlite documentation for more information about table ad column constraints.

Last Modified By fields and foreign keys

In SQL Server 2012, I have a User table to store application users. I also have an Organization table which has a LastModifiedBy field in which I would like to store the UserID of the last person to modify the values within the table via an ASPX page. Should I create a foreign key relationship between the LastModifiedBy field and the UserID field within the Users table?
I would also like to add a LastModifiedBy field to the Users table itself. Should/can I create a self referencing foreign key constraint on this table? If this is possible, is it a horrible idea?
Any perspectives on pros and cons of creating these foreign key constraints would be greatly appreciated.
What you are describing is what foreign keys are made for. These foreign keys are at the very core of relational databases. Even if they might give a slight performance impact when inserting new rows, because it has to check if the referenced key exists, it should not be avoided.