SQL Server + Composite key or Unique Id - sql

I am fairly new to database design, for many to many relationship, what is the differences and implications of creating a composite key and a unique id for e.g.
Country table
CountryID
CountryName
Language table
LanguageID
LangugageName
Many to Many table - using composite:
CountryID Pkey
LanguageID Pkey
OR
Using unique Id:
AutoID Pkey
CountryID
LanguageID

Composite Key :
A composite key is a combination of more than one column to identify a unique row in a table.
composite key can be a primary key .
PRIMARY KEY
The PRIMARY KEY constraint uniquely identifies each record in a database table.
so its all depend on your requirement
in first design
Many to Many Table:
Using composite:
CountryID Pkey
LanguageID Pkey
if you use this desing than CountryID and LanguageID is composite primary key.i.e here
data of the table will be
CountryId LaguageID
1 1 //valid
1 2 //valid
1 3 //valid
1 1//not valid data as its form composite primary key
and in second design
Using Unique Id:
AutoID Pkey
CountryID
LanguageID
AutoID is become primary key so this will allow data lke thsi
AutoId CountryId LaguageID
1 1 1 //valid
2 1 2 //valid
3 1 3 //valid
4 1 1 //valid as AutoID is primary key
1 2 3 // invalid as AutoID is prinary key
hope this presentation help you to understand difference

what is the differences and implications of creating a composite key and a unique id for e.g.
You'll need to create a "natural" key on {CountryID, LanguageID} to avoid duplicated connections in any case. The only question is whether you'll also need a "surrogate" key on {AutoID}?
Reasons for a surrogate key:
There are child tables that reference this junction table (and you'd like to keep their FKs slim or prevent ON CASCADE UPDATE propagation).
You are using an ORM that likes simple PKs.
Unless some of these reasons apply, use only the natural key.
BTW, under a DBMS that supports clustering, a natural key like this is usually a good candidate for a clustering key. If you cluster the table, every other index (such as the one underneath the surrogate key) has extra overhead (compared to an index in a heap-based table) since it needs to keep the copy of clustering key data and can cause a double-lookup.
See also: A column as primary key or two foreign keys as primary key.

Related

Sqlite - composite PK with two auto-incrementing values [duplicate]

I have a composite primary key {shop_id, product_id} for SQLite
Now, I want an auto-increment value for product_id which resets to 1 if shop id is changed. Basically, I want auto-generated composite key
e.g.
Shop ID Product Id
1 1
1 2
1 3
2 1
2 2
3 1
Can I achieve this with auto-increment? How?
Normal Sqlite tables are B*-trees that use a 64-bit integer as their key. This is called the rowid. When inserting a row, if a value is not explicitly given for this, one is generated. An INTEGER PRIMARY KEY column acts as an alias for this rowid. The AUTOINCREMENT keyword, which can only be used on said INTEGER PRIMARY KEY column, contrary to the name, merely alters how said rowid is calculated - if you leave out a value, one will be created whether that keyword is present or not, because it's really the rowid and must have a number. Details here. (rowid values are generally generated in increasing, but not necessarily sequential, order, and shouldn't be treated like a row number or anything like that, btw).
Any primary key other than a single INTEGER column is treated as a unique index, while the rowid remains the true primary key (Unless it's a WITHOUT ROWID table), and is not autogenerated. So, no, you can't (easily) do what you want.
I would probably work out a database design where you have a table of shops, a table of products, each with their own ids, and a junction table that establishes a many-to-many relation between the two. This keeps the product id the same between stores, which is probably going to be less confusing to people - I wouldn't expect the same item to have a different SKU in two different stores of the same chain, for instance.
Something like:
CREATE TABLE stores(store_id INTEGER PRIMARY KEY
, address TEXT
-- etc
);
CREATE TABLE product(prod_id INTEGER PRIMARY KEY
, name TEXT
-- etc
);
CREATE TABLE inventory(store_id INTEGER REFERENCES stores(store_id)
, prod_id INTEGER REFERENCES product(prod_id)
, PRIMARY KEY(store_id, prod_id)) WITHOUT ROWID;

What's the difference between alternate key and Foreign key in database

What's the difference between alternate key and Foreign key in database
Alternate key is unique key reminiscent of primary key that can be a column or the column's group of the table. Further, alternate key is unique all time in the table. Unlike the primary key, unique key is non-clustered index type as well as
foreign key is to create a relationship with another table and it's used for data integrity.
|-------------------------------------|---------------------------------|
|**alternate key** |**foreign key** |
|-------------------------------------|---------------------------------|
|unique |non-unique |
|-------------------------------------|---------------------------------|
|never accept null value |accept null value |
|-------------------------------------|---------------------------------|
|can be multiple |can be multiple |
|-------------------------------------|---------------------------------|
|Independent another table |Dependent another table |
|-------------------------------------|---------------------------------|
|Create Noncluster index automatically|Cannot create index automatically|
|-------------------------------------|---------------------------------|
Alternate Key
All the keys which are not primary key are called an alternate key.
Foreign Key
A foreign key is a column which is added to create a relationship with another table. Foreign keys help us to maintain data integrity and also allows navigation between two different instances of an entity

SQL Primary Key Duplicate Values

I have a table with 2 primary key columns : ID and StudentID.
ID column is set to isIdentity = Yes with auto increment.
I've tested it multiple times before, but for some reason this time, when I insert a duplicate value on StudentID, it does not throw the error but instead added it on to the database. 2 of the same values are displayed when I show the table data.
What can be the problem here?
You have a compound primary key on ID and StudentID. That means you the combination of ID and StudentID together must be unique. Since ID is an identity column that combination of ID and StudentID will always be unique (because ID is already unique on its own).
You can change the primary key to be on ID only. Then you can add a unique index on StudentID. For example:
create unique index idx_studentID on yourTable(StudentID)
That will insure that the StudentID column, in fact, contains only unique values.
It seems like you may not actually need ID column, but that's a little wider discussion than your original question.
You can't have 2 "primary keys". You can have a compound primary key (meaning the combination needs to be unique, which is what it sounds like you have now. Or, You can have one "primary" key and one "unique" constraint which is what it sounds like you want.
You cannot have 2 Primary Keys. You can have multiple Unique Keys if needed, which should help you in your case. Make sure to go back to your table creation and double check which column is your Primary Key and work from there.
Do not mix up identity, primary key and unique key.
Any table can have identity key which you can setup on table. Here seed can be say 1, then increment it by 1. So incremental order will like 1,2,3...and so on.
Primary key, one can define on specific column of the table. Identity key can be used as primary key. But you can have identity column as well primary key on same table. Primary key is one and only for the table.So if you are treating identity as primary key, then you will have no further table column as primary key.
Unique key, can be more than one column with your table.
While fetching rows from table data, if you provide combination of identity key, primary key and unique key then search will be fastest
During my first response, I have mentioned that one can generate identity column by soft coding and it will not be treated as primary key.Following is syntax one can use while creating table.
1] If one wish to set identity column as primary key
--id int identity(1,1) primary key
2] If one doesn't wish to set identity column as primary key and still wish
to us identity column then donot us word primary key for identity column.
--id int identity(1,1)
In this 2] case scenario, one may create primary key on other table column.

Partial index on value from related table, rather than foreign key?

I'm working on a learning platform where students belong to a team, each of which belongs to a curriculum:
CREATE TABLE teams (
id SERIAL,
name string NOT NULL,
curriculum_id integer NOT NULL
);
CREATE TABLE curricula (
id SERIAL,
name string NOT NULL
);
CREATE UNIQUE INDEX index_curricula_on_name ON curricula USING btree (name);
Curricula have to be unique by name, and while most curricula are allowed to have multiple teams associated to them, one can not. I am trying to add a partial (unique) index on the teams table so as to add a restraint on the curriculum.
I know I can partially constrain the curriculum id itself with...
CREATE UNIQUE INDEX index_teams_on_curriculum_id ON teams USING btree (curriculum_id)
WHERE curriculum_id = 1;
... but this is not viable, as the IDs for the curriculum will vary across environments (dev, staging, etc).
Is there a way to constrain the teams.curriculum_id column by curricula.name instead?
You could implement something like this with a trigger or with a fake immutable function in a CHECK constraint. Both have their weak spots.
But this can also be implemented with pure SQL - only using NOT NULL, CHECK, UNIQUE and FK constraints. No weak spot.
CREATE TABLE curriculum (
curriculum_id serial PRIMARY KEY
, curriculum text UNIQUE NOT NULL
, team_unique boolean UNIQUE NOT NULL
, CONSTRAINT curriculum_team_uni UNIQUE (curriculum_id, team_unique) -- for multicolumn FK
);
CREATE TABLE team (
team_id serial PRIMARY KEY
, team text NOT NULL
, curriculum_id integer NOT NULL
, team_unique boolean NOT NULL
-- , CONSTRAINT fk1 FOREIGN KEY (curriculum_id) REFERENCES curriculum
, CONSTRAINT fk2 FOREIGN KEY (curriculum_id, team_unique)
REFERENCES curriculum (curriculum_id, team_unique)
);
CREATE UNIQUE INDEX team_curriculum_uni_idx ON team (team_unique)
WHERE team_unique;
Add a boolean NOT NULL column to parent and child table and make it UNIQUE in the parent table. So only one row in curriculum can be marked unique - to implement your restrictive requirement:
one can not
A partial unique index team_curriculum_uni_idx enforces only a single reference to it.
If there were multiple unique curriculums (to be referenced once only), we would remove the UNIQUE constraints on curriculum.team_unique and extend the partial unique index on team to (curriculum_id, team_unique).
The FK (fk2) forces to inherit the combination of columns.
This makes it simple to add a UNIQUE constraint to enforce a single team for the unique curriculum.
The default MATCH SIMPLE behavior of Postgres FK constraints only enforces combinations without NULL values. We can either use MATCH FULL or another plain FK (fk1) to enforce only existing curriculum_id. I commented the additional FK since we don't need it in this configuration (both FK columns defined NOT NULL).
SQL Fiddle.
Related:
MATCH FULL vs MATCH SIMPLE in foreign key constraints
CONSTRAINT to check values from a remotely related table (via join etc.)
Disable all constraints and table checks while restoring a dump
Enforcing constraints “two tables away”

column pk dual varchars or int?

Imagine a table that has a JobID and a SubJobID.
The combination of JobID + SubJobID make the row unique.
For instance:
JobID = CAX100
SubJobID = CA00
JobID = CAX200RW
SubJobID = CA00
JobID = CAX200YYXZ
SubJobID = CA01
etc...
These are valid rows, but if I try to again insert JobID=CAX100 and SubJobID=CA00 then this is not allowed and should error.
So currently should I keep JobID and SubJobID the combination of both as a primary key? Or should I introduce an int as a primary key (maybe an autoincrement int)? I know ints are better and smaller for primary keys, but then how do I ensure the uniqueness of JobID + SubJobID if I introduce a number as a primary key?
Currently I have JobID and SubJobID as composite primary keys I understand that, that is what I currently have, but what is recommended having both columns as pk (varchar) or introduce a new column (int type with auto number) and create a unique constraint on JobID + SubJobID?
If you add a surrogate autoincrement integer column, you still need a unique index on the JobID, SubJobID columns. This is the natural primary key.
It may not add much value except using more disk and memory to store the extra column.
Saying that, if the composite (JobID, SubJobID) index is used in child tables as a foreign key, it can make more sense to use one. 10000 rows here could have 10 million child rows: then the varchar overhead matters.
However, there is no truth in anything you read that says
Thou shalt always have an identity/autoincrement primary key
It is an implementation decision for performance depending on the design.
Personally, I would define an integer Primary Key and a unique index on the 2 varchar fields. This is assuming that your database application is non-trivial and performance is an issue.
If you only have a few dozen records in this table, on the other hand, it is possible to over-engineer things.