In SQL does a Primary Key in a create table enforce uniqueness? - sql

Im wondering if on a relational table I set the two values below as a PRIMARY KEY if that automatically makes the table know that all entries should be unique....
CREATE TABLE UserHasSecurity
(
userID int REFERENCES Users(userID) NOT NULL,
securityID int REFERENCES Security(securityID) NOT NULL,
PRIMARY KEY(userID,securityID)
)
or do I need to be more explicit like this...
CREATE TABLE UserHasSecurity
(
userID int REFERENCES Users(userID) NOT NULL,
securityID int REFERENCES Security(securityID) NOT NULL,
PRIMARY KEY(userID,securityID),
UNIQUE(userID,securityID)
)

You don't need UNIQUE here. PRIMARY KEY will make sure there is no duplicate (userID,securityID) pairs.

No, you don't need to specify UNIQUE in addition to PRIMARY KEY. A primary key by definition must be unique.

A PRIMARY KEY has to be unique, so you only need to declare as a primary key. The underlying index is unique by definition.
Creating Unique Indexes

Related

Sql creating table consisting of keys from other tables

this is probably a simple question but I am quite new to SQL and databases, so I have been following this site: https://www.postgresqltutorial.com/postgresql-foreign-key/ to try and create a table that consist of primary keys from other tables.
Here I have the structure of the database in an excel overview. With colors showing the relations. i am having problems with the One-To-Many tables. As I get the same error every time "ERROR: column "id" referenced in foreign key constraint does not exist
SQL state: 42703".
The SQL query:
DROP TABLE IF EXISTS ingredient_to_unit_relations;
DROP TABLE IF EXISTS ingrediens;
CREATE TABLE ingrediens (
id serial,
name_of_ingredient varchar(255),
price_per_unit int,
PRIMARY KEY (id)
);
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY,
PRIMARY KEY (ingredient_relation_id),
constraint Fk_ingredient_id
FOREIGN KEY (id)
REFERENCES ingrediens (id)
);
You need to define the column in order to declare it as a foreign key:
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY,
ingredient_id int,
PRIMARY KEY (ingredient_relation_id),
constraint Fk_ingredient_id FOREIGN KEY (ingredient_id) REFERENCES ingrediens (id)
);
I might recommend some somewhat different naming conventions (I changed the name id in the table above):
CREATE TABLE ingredients (
ingredient_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar(255),
price_per_unit int
);
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
ingredient_id int,
CONSTRAINT Fk_ingredient_id FOREIGN KEY (ingredient_id) REFERENCES ingredients (ingredient_id)
);
Notes:
I am a fan of naming primary keys after the table they are in. That way, foreign keys and primary keys usually have the same name (and you can use using if you choose).
Avoid SERIAL. GENERATED ALWAYS AS IDENTITY is now recommended.
You can inline primary key constraints (as well as other constraints).
There is not generally a need to repeat the table name in a column (other than the primary key). So, name instead of name_of_ingredient.
Using int for a monetary column is suspicious. It doesn't allow smaller units. That might work for some currencies but in general I would expect a numeric/decimal type.

Error contains no primary or candidate keys that match the referencing column

This is my first Table : Tours
CREATE TABLE [dbo].[Tours] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[TourId] INT NOT NULL,
[TCountry] NVARCHAR (50) NULL,
[TName] NVARCHAR (100) NULL,
CONSTRAINT [PK_Tours] PRIMARY KEY CLUSTERED ([TourId]),
CONSTRAINT [FK_Tours_ToTourDates] FOREIGN KEY ([TourId]) REFERENCES [TourDates]([TourId]));
and this is the next, Table:TourDates
CREATE TABLE [dbo].[TourDates] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[TourId] INT NOT NULL,
[TourStartDate] DATETIME NULL,
CONSTRAINT [PK_TourDates] PRIMARY KEY CLUSTERED ([Id] ASC));
for first table I have this Error :
SQL71516 :: The referenced table '[dbo].[TourDates]' contains no
primary or candidate keys that match the referencing column list in
the foreign key. If the referenced column is a computed column, it
should be persisted.
How can one define a Candidate key for TourId column in TourDates Table??
I believe that you should be doing something else than you are doing right now.
Tours table seems to hold every tour which should be in 1:N relationship with TourDates provided that I understand it correctly.
Thus, your FOREIGN KEY constraint should actually be declared on TourDates, not Tours table.
As to your issue (which I believe wouldn't if you switch those relationships to what they should be in my understanding) in such cases you would normally need to create a unique index on that column.
You can't reference a column which may contain several exact same values via foreign key constraint, thus the need for some sort of a unique key.
Edit after comment:
ALTER TABLE [dbo].[TourDates]
ADD CONSTRAINT FK_Tour_TourDates
FOREIGN KEY ([TourId]) REFERENCES [dbo].[Tours]([TourId]) ON DELETE CASCADE

SQL Multiple Foreign Keys as Primary Keys

If I declare the table below does it implicitly imply that both the foreign keys make a unique primary key or do I need to do something more to make both attributes as a primary key?
CREATE TABLE Report_has_Items
(
ReportID int REFERENCES Report(ReportID) NOT NULL,
ItemID int REFERENCES Item(ItemID) NOT NULL
)
Essentially both attributes which are foreign keys from other tables, together would form a unique key.
No it doesn't. The above table has no primary key. If you want to use the fields as a primary key use:
CREATE TABLE Report_has_Items(
ReportID int REFERENCES Report(ReportID) NOT NULL,
ItemID int REFERENCES Item(ItemID) NOT NULL,
PRIMARY KEY (ReportID, ItemID)
)
or something similar depending on your sql dilect.
Let's name our constraints, eh?
CREATE TABLE dbo.Report_has_Items(
ReportID int NOT NULL,
CONSTRAINT [FK_RHI_Report] (ReportId) REFERENCES dbo.Report(ReportID),
ItemID int NOT NULL,
Constraint [FK_RHI_Item] (ItemId) REFERENCES dbo.Item(ItemID),
CONSTRAINT [PK_RHI] PRIMARY KEY (ReportID, ItemID)
)
I am not sure i understand your question completely but i assume you are trying to create a composite primary key (primary key with more than one attribute). You could do the following.
CREATE TABLE Report_has_Items(
ReportID int references Report(ReportID),
ItemID int references Item(ItemID),
PRIMARY KEY (ReportID , ItemID )
);
Note:The pair (ReportID , ItemID ) must then be unique for the table and neither value can be NULL.
Here is a very useful link for SQL Queries

What's the difference between these SQL syntaxes?

I was looking for info on foreign keys.... AGAIN! ... and happened to notice on webschools.com they have different examples of the same thing. for the foreign key example they have
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
CREATE TABLE Orders
(
O_Id int NOT NULL PRIMARY KEY,
OrderNo int NOT NULL,
P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
)
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
)
now..........
what's the difference?...
How do I know which one I'm suppose to use for my database? I have a feeling this will help resolve a lot of the confusion I'm having with SQL...
No difference in effect: They achieve exactly the same thing.
I prefer the in-line version, because it puts the fk definition as close to the column definition as possible.
There's a 3rd way - a separate alter table statement (which I think is the "official" way):
alter table orders
add contraint fk_PerOrders
foreign key p_id references persons(p_id);
You may find some databases don't support one version or the other.
All of them are doing same thing. Use the one which you feel is easy to understand.
All do same (three ways):
In first, you first defined P_Id as int then defined foreign key constraint.
In second, P_Id int FOREIGN KEY REFERENCES Persons(P_Id). P_Id is defecation and foreign key constraint defecation in same line.
In third, a foreign key constraint name is also give fk_PerOrders. that can be useful later when you wants to drop constraint. e.g.
ALTER TABLE Orders
DROP FOREIGN KEY fk_PerOrders
Its always good practice to give name to a constraint.

could unique key ( not primary ) be a parent for declarative foreign key constraint

Naive question with the answer "No" , I believe, but still would like to ask.
Table_parent
pk_parent_surrogate
parent_natural_unique_key
Table_child
pk_child_surrogate
child_natural_NOT_unique
Is that true that the only possible declarative relationship among main database vendors is
pk_parent_surrogate ----------< pk_child_surrogate
and we can't have declarative constraint or foreign key in other words for pair
parent_natural_unique_key -------< child_natural_NOT_unique
My answer here is based on my MS SQL knowledge - although I believe the same answer is correct for ANSI standards as well, i'm not 100% sure...
YES - you CAN do this as long as you've got a unique constraint on the column in your parent table that you want to use as the anchor column for the key.
You can create a FOREIGN KEY constraint as part
of the table definition when you create a table.
If a table already exists, you can add a
FOREIGN KEY constraint, provided that the
FOREIGN KEY constraint is linked to an existing
PRIMARY KEY constraints or UNIQUE constraint in
another, or the same, table. A table can contain
multiple FOREIGN KEY constraints.
And as an example of this sort of key...
use tempdb
CREATE TABLE parent(
pk int identity primary key,
candidate_key int unique not null)
CREATE TABLE child(
pk int identity primary key,
join_key int references parent(candidate_key))
See here for more information.
Try code like this:
create table testunique (id int identity(1,1) primary key, otherid int)
go
create unique index ixOther on testunique(otherid)
go
create table testFK (id int identity(1,1) primary key, someid int)
go
alter table testFK add constraint fkTest foreign key (someid) references testunique(otherid)
Rob