Can someone explain this statement (foreign key) of a table - database

CREATE TABLE genres
(
genre_id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
genre VARCHAR(255) N[enter image description here][1]OT NULL,
parent_id INT NULL,
-- Will be thankful to you for explaining the 3 lines below
PRIMARY KEY (genre_id),
CONSTRAINT fk_parent
FOREIGN KEY(parent_id) REFERENCES genres(genre_id)
);

PRIMARY KEY(genre_id) - means that at most one row in the table GENRES can have a specific value. In other words, for every row in the table, the value in GENRE_ID column will be unique. Additionally the value in the column cannot be null, and that value serves to identify the row uniquely without needing any other value to identify the row. The DDL shows that the database will generate the value for the GENRE_ID column by default.
The "CONSTRAINT fk_parent FOREIGN KEY(parent_id) REFERENCES genres(genre_id) )" means that the database-manger
will enforce that if column PARENT_ID is not null then the value in this column must be an existing value in a row in the GENRES table. Another way of thinking about this is that the database-manager is asked to maintain a parent-child relationship, so a genre may have sub-genres (i.e. a genre may have child genres). So the database manager would not let you specify that a particular genre was a sub-genre of a non-existent parent genre.
The database manager might also enforce the relationship is valid over time, for example it might prevent a delete or update action if that delete would produce orphan rows (i.e. child rows with no parent row) , or it may set such parent_id values to null, depending on the DDL and Db2-version/platform.

Answer:Self Referencing Foriegn Key
https://www.red-gate.com/simple-talk/sql/t-sql-programming/questions-about-primary-and-foreign-keys-you-were-too-shy-to-ask/

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.

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
)

What should happen with a column after the primary key constraint was removed?

I am talking about the normalization of a primary key. So let's say my primary key column is of type nvarchar, which violates the rules of normalization. After removing the primary key constraint and the identity specification from the desired column. I need to create a new column which will be the new primary key of that table.
My question is, what should happen with the previous primary key?
I've got an answer that sounds like: "the column should became a semantic key", but i can't understand this answer.
It's not unusual when designing a database schema to use a SURROGATE primary key. The idea is to give each record a unique and permanent identifier so it can be easily referenced by applications and foreign keys. This key has no meaning. Knowing the surrogate key gives you no information about the content of the record. The user of your application would never see this value.
On the other hand, your record may have a SEMANTIC primary key. This is a unique value that identifies this data to that makes sense to the user.
For example, let's say you have a table of Employees. The employer assigns each employee a unique Employee ID Number. Let's say you store this value as a string. To the user that value serves as the unique identifier that refers to that employee. Meanwhile, your table may have a numeric column that serves as the unique identifier for that record.
create table Employee ( EmployeeRecordID int identity(1,1) primary key,
EmployerAssignedID nvarchar(12),
EmployeeName nvarchar(60),
Salary money )
insert into Employee ( EmployerAssignedID, EmployeeName, Salary ) values
( '#ABC100', 'Fred', 25000.12 ),
( '#AZZ314', 'Mary', 37700.00 ),
( '#MAA719', 'Fran', 34444.04 ),
( '#MZA977', 'Mary', 36000.00 )
As each record is added, SQL Server generates a unique EmployeeRecordID for each record, starting with 1. This is the SURROGATE key. Within your database and within your application, you would use this value to reference the record.
But when your application is communicating with the users, you would use the EmployerAssignedID. This is the SEMANTIC primary key. It makes sense to your users to use this value to search for a particular employee.
A primary key is no more than a unique index which can't have NULL value as a key. Like any of indexes it can be clustered or nonclustered.
Deleting a clustered index makes table become a heap with changes in structure and behaviour. Deleting a nonclustered index is just deallocation its space and does not affect that table and other indexes on the table as well.
So after deleting you just have a column(s) with unique values and you are able to consider them as a semantic key until some duplicate values are inserted.

Is there is a constraint to make sure one column has and only matched column

I have a problem to set correct constraint to make sure one column has and only has one matched column within the table.
For example, company Apple has Bloomberg ticker AAPL:US and only has this ticker. Otherwise, SQL Server will notice there is a error.
I try to use constraint with unique, but it does not work.
I imagine that your schema might be a standard one using a junction table. That is, your tables might look something like:
company (id, name)
ticker (id, name)
company_ticker (id_company, id_ticker)
That is, the company_ticker table is a junction table which stores the relationships between companies and tickers. Normally, this table would by default be many-to-many. But if you want to restrict a company to having only one ticker, then you may place a unique constraint on the id_company column:
CREATE TABLE company_ticker (
id_company INT NOT NULL,
id_ticker INT NOT NULL,
PRIMARY KEY (id_company, id_ticker),
CONSTRAINT cnstr UNIQUE (id_company)
);
With the above unique constraint in place, your schema will only allow a given company to have one relationship with some ticker.

SQL Server: Unable to create relationship

I was trying to create a table that has a one to many relationships. but it seems that adding a foreign key in Personal is not working. I am trying to link a Personal Information table to a address table? what is the solution for this error?
Address table saved successfully
Personal table
Unable to create relationship 'FK_Personal_Address'.
Cascading foreign key 'FK_Personal_Address' cannot be created where the
referencing column 'Personal.ID' is an identity column. Could not
create constraint. See previous errors.
The primary key in the Person table is presumably an identity. This is an auto-incrementing integer field.
You need to make the foreign key in the address table of type int, not identity. It will hold integers which correspond to Person records, but you don't want the foreign key to auto-increment. For each record in the child table (address) you will set a specific value for the foreign key indicating to which parent record (Person) it belongs.
Example:
INSERT person (firstname, lastname) VALUES ('John', 'Smith')
This will insert the new person record and the field personid will be filled automatically because it is an IDENTITYfield.
Now to insert an address from John Smith you need to know his personid. For example:
-- Say, for example, personid of John Smith is 55
INSERT address (personid, street, city) VALUES (55, 'High Street', 'London')
So in the person table the personid is generated automatically but in the address table you specify the value that matches an existing person. That's the whole point of a foreign key.
Without more information about your schema it's hard to guess the problem.
I made sure to follow identity, int and primary key discussed in above answer. However, I was still getting the same error.
'xReason' table saved successfully
'xAddress' table
- Unable to create relationship 'FK_xAddress_xReason'.
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_xAddress_xReason". The conflict occurred in database "databaseName", table "dbo.xReason", column 'xReasonID'.
This error resolved when I inserted some data into a Reason table. (table that had a primary key)
If you read this far, this might be your problem.
Without seeing the structure of the tables in the question, I believe the most likely cause is the column in your child table (Address) is marked as an Identity column. In a foreign-key relationship, the parent determines the value of the field, not the child. The column may be the PK in the child table, but not an Identity.
it seem that you try to create a foreign key on Personal.ID related to itself.
You probably want to do something like :
ALTER TABLE Adress WITH NOCHECK ADD CONSTRAINT [FK_Adress_Personnal] FOREIGN KEY(Personal_Id)
REFERENCES Personal (ID)
I got the same error with adding foreign key constraints to one of my tables.
I found the workaround was to add it WITH NOCHECK. why I was able to add the other two foreign keys WITH CHECK but not the third foreign? I found that it was not the table but the order of the foreign key to be added. Any insight to this will be much appreciated.

Resources