Difference between UniqueConstraint and multiple Primary Keys - sqlalchemy

I have a many-to-many relationship table. Naturally I want every record to be unique. So I checked the docs how should I make a unique constrained on the columns.
association_table = Table(
"association",
Base.metadata,
Column("left_id", ForeignKey("left.id")),
Column("right_id", ForeignKey("right.id")),
# explicit/composite unique constraint. 'name' is optional.
UniqueConstraint('left_id', 'right_id', name='uix_1')
)
However the dedicated docs on many-to-many relationship configuration advises for a composite primary key.
association_table = Table(
"association",
Base.metadata,
Column("left_id", ForeignKey("left.id"), primary_key=True),
Column("right_id", ForeignKey("right.id"), primary_key=True),
)
Is there any difference for this application example and if yes, what?

Related

Why normal entity which dependents to parent table is can not named weak entity?

There is one parent table "region". And weakentity is table "hospital"
create table hospital( name varchar(32) id int, FOREIGN KEY(id) REFERENCES region (id),PRIMARY KEY(name,id),
and normal entity which dependents to region "hosp" create table hosp (name varchar(32), id int, r_id int, FOREIGN KEY (r_id) REFERENCES region(id), PRIMARY KEY(id)
No in your case weak entity is hospital and hosp because dependent to region
Firstly understand about weak entity and normal entity
In a relational database, a weak entity is an entity that cannot be uniquely identified by its attributes alone; therefore, it must use a foreign key in conjunction with its attributes to create a primary key. The foreign key is typically a primary key of an entity it is related to.
and normal entity is a thing, person, place, unit, object or any item about which the data should be captured and stored in the form of properties, workflow and tables. While workflow and tables are optional for database entity, properties are required (because entity without properties is not an entity)

Using circular FK references in a database

I have two (mysql) tables -- company and user. They are structured as follows:
`user`
- id
- company_id (FK to company)
- name
`company`
- id
- name
- admin_user_id (FK to user)
The user table foreign keys to the company table, and vice versa.
I was wondering if the above pattern is ok, and if it's not why it's not, what could be done to improve it.
At a high level, your data model makes sense. However, you have no guarantee that admin_user_id points to a user in the same company. You can solve this by doing:
create table users (
user_id int auto_increment primary key,
company_id int,
name varchar(255),
unique (company_id, user_id) -- redundant but desirable for the foreign key reference
);
create table companies (
company_id int auto_increment primary key,
name varchar(255),
admin_user_id int,
foreign key (company_id, admin_user_id) references users(company_id, user_id)
);
alter table users
add constraint fk_users_company_id
foreign key (company_id) references companies (company_id);
If it is an accurate representation of your business domain then that's what really matters. There is a possible problem in SQL however. SQL only allows one table to be updated at once so either company or user has to come first. Normally you have to allow the constraint to be broken temporarily, either when you insert a new company with no corresponding user, or insert a new user with no corresponding company. To achieve that you can make one of the foreign keys nullable or you can temporarily disable the constraint.
Some data modellers dislike circular dependencies, even in purely conceptual models where the limitations of SQL are irrelevant. A few people will perceive circular dependencies as a modelling mistake - wrongly in my opinion. Disapproval of circular dependencies seems to be associated with ER modelling specifically. Interestingly, circular self-referential dependencies are taken for granted in Object Role Modelling which even has a special notation for them (ring constraints).

When to use foreign key as a primary key at the same time?

I have get an intermediate table ArticleLanguage
idArticleLanguage
ArticleId
LanguageId
Name
Foreign keys are:
ArticleId
LanguageId
Should I use primary keys for:
ArticleId
LanguageId
Because these fields are primary keys in related tables?
Link / Junction Tables
Assuming the linked tables are defined as:
CREATE TABLE Article
(
ArticleId INT PRIMARY KEY
-- ... other columns
);
CREATE TABLE Language
(
LanguageId INT PRIMARY KEY
-- ... other columns
);
As per #JulioPĂ©rez Option 1, the link table could be created as:
CREATE TABLE ArticleLanguage
(
ArticleId INT NOT NULL,
LanguageId INT NOT NULL,
Name VARCHAR(50),
-- i.e. Composite Primary Key, consisting of the two foreign keys.
PRIMARY KEY(ArticleId, LanguageId),
FOREIGN KEY(ArticleId) REFERENCES Article(ArticleId),
FOREIGN KEY(LanguageId) REFERENCES Language(LanguageId)
);
i.e. with a composite primary key consisting of the two foreign keys used in the "link" relationship, and with no additional Surrogate Key (idArticleLanguage) at all.
Pros of this approach
Enforces uniqueness of the link, i.e. the same ArticleId and LanguageId cannot be linked more than once.
Saves an unnecessary additional surrogate key column on the link table.
Cons of this approach:
Any downstream tables which needs to reference this link table, would need to repeat both keys (ArticleId, LanguageId) as a composite foreign key, which would again consume space. Queries involving downstream tables which reference ArticleLanguage would also be able to join directly to Article and Language, potentially bypassing the link table (it is often easy to 'forget' that both keys are required in the join when using foreign composite keys).
SqlFiddle of option 1 here
The alternative (#JulioPĂ©rez Option 2), would be to to keep your additional surrogate PK on the reference table.
CREATE TABLE ArticleLanguage
(
-- New Surrogate PK
idArticleLanguage INT NOT NULL AUTO_INCREMENT,
ArticleId INT NOT NULL,
LanguageId INT,
Name VARCHAR(50),
PRIMARY KEY(idArticleLanguage),
-- Can still optionally enforce uniqueness of the link
UNIQUE(ArticleId, LanguageId),
FOREIGN KEY(ArticleId) REFERENCES Article(ArticleId),
FOREIGN KEY(LanguageId) REFERENCES Language(LanguageId)
);
Pros of this Approach
The Primary Key idArticleLanguage is narrower than the composite key, which will benefit any further downstream tables referencing table ArticleLanguage. It also requires downstream tables to join through the ArticleLanguage link table in order to get ArticleId and LanguageId, for further joins to the Language and Article tables.
The approach allows for an additional use case, viz that if it IS possible to add the same link to Language and Article more than once (e.g. two revisions or two reprints etc), then the UNIQUE key constraint can be removed
Cons of this Approach
If only one unique link per Article and Language is possible, then the additional surrogate key is redundant
SqlFiddle of option 2 here
If you're asking for an opinion, I would stick with option 1, unless you do require non-unique links in your ArticleLanguage table, or unless you have many further downstream tables which reference ArticleLanguage (this would be unusual, IMO).
Table per Type / per Class Inheritance
Unrelated to OP's post, but another common occurrence where a Foreign Key can be used as a Primary Key in the referencing table is when the Table per Type approach is taken when modelling an object oriented class hierarchy with multiple subclasses. Because of the 0/1 to 1 relationship between subclass and base class tables, the base class table's primary key can also be used as the primary key for the subclass tables, for instance:
CREATE TABLE Animal
(
AnimalId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-- Common Animal fields here
);
CREATE TABLE Shark
(
AnimalId INT NOT NULL PRIMARY KEY,
-- Subclass specific columns
NumberFins INT,
FOREIGN KEY(AnimalId) REFERENCES Animal(AnimalId)
);
CREATE TABLE Ewok
(
AnimalId INT NOT NULL PRIMARY KEY,
-- Subclass specific columns
Fleas BOOL,
FOREIGN KEY(AnimalId) REFERENCES Animal(AnimalId)
);
More on TPT and other OO modelling in tables here
You have 2 ways:
1) Put "ArticleId + LanguageId" as your only primary key in "intermediate table" and you can name it as "idArticleLanguage". This is called a "composite" primary key because it is composed by 2 (in other case more than 2) fields, in this case 2 foreign keys (PK= FK + FK).
2) Create "idArticleLanguage" that has no relation to the other two "id" and set it as primary key.It can be a simple auto-increment integer.
Both alternatives are accepted. Your election will depend on the goal you want to achieve because what happens if you need to add in this intermediate table the same Article with the same language (Wilkommen German for example) because you have 2 different editions of the article? if you choose alternative 1 it will throw an error because you will have the same composite primary key for 2 rows then you must choose alternative 2 and create a completely different primary key for this table
In any other case (or purpose) you can choose alternative 1 and it will work perfectly
About the change of your question title:
When use foreign key as primary key in the same time?
I will explain it with this example:
You have 2 tables: "country" and "city". "country" have all the countries of the world, "city" have all the cities of the world. But you need to know every capital in the world. What you should do?
You must create an "intermediate table" (named as "capital") that will have every capital on the world. So, we know that country have it's primary key "idcountry" and city have it's primary key is "idcity" you need to bring both as foreign keys to the table "capital" because you will need data of "city" and "country" tables to fill "capital" table
Then "capital" will have it's own primary key "idcapital" that can be a composite one "idcity+idcountry" or it can be an auto-increment integer in both cases you must have "idcity" and "idcountry" as foreign keys on your "capital" table.

How do you model disjoint relationships between two relations in MySQL Workbench?

You have the option to uncheck Mandatory in the foreign key tab of the relationship window, but that doesn't fully capture the meaning of a disjoint relationships, which is an EITHER-OR relationship between multiple relations.
Your referring to the mandatory property of the foreign key makes me believe you are either misunderstanding the meaning of a disjoint relationship, or implementing it with a relation in the wrong "direction".
Let's say we want to implement the following schema:
class: Staff Member
class: Permanent (specialises Staff Member)
class: Temporary (specialises Staff Member)
a Staff Member is either a Permanent employee or a Temporary contractor
A corresponding EER schema would be (MySQL syntax):
CREATE TABLE staff_member (
id INT PRIMARY KEY,
name VARCHAR(20) NOT NULL
);
CREATE TABLE permanent (
id INT PRIMARY KEY,
next_appraisal DATETIME NOT NULL,
FOREIGN KEY (id) REFERENCES staff_member(id)
);
CREATE TABLE temporary (
id INT PRIMARY KEY,
contract_end DATETIME NOT NULL,
FOREIGN KEY (id) REFERENCES staff_member(id)
);
Notice the foreign key is from the specialised entity to the parent entity (id being the primary key, it is also always mandatory by definition).
This still doesn't answer your question. How to model the disjoint property of this relationship? You cannot do this easily (neither can you model that a specialisation is complete, by the way).
Many RDBMS support the use of CHECK constraints in order to enforce these extra conditions, but MySQL does not (beware, the syntax is accepted by the MySQL parser, but the declaration is ignored). However, simple workarounds exist that result in the same effect.

Must it be a many-to-many relationship when two foreign keys occur?

This question maybe be silly, but I just want to confirm whether I get the basic understanding correctly, so:
Must it be a many to many relationship when two foreign keys occur in a table?
Or are there any other terms/reasons when two foreign keys are in a table?
No.
Counter-example:
create table eg1 (
id int primary key,
id1 int,
id2 int,
foreign key (id1) references othertable.id,
foreign key (id2) references sometable.id,
UNIQUE INDEX `id1_UNIQUE` (`id1` ASC)
);
This is not a many-to-many relationship because id1 is unique. It has two foreign keys, but is expressing a 1:n and a 1:1 relationship to the two other tables.
I don't believe that will always be the case. I can think of several situations where there are multiple FKeys in a table. For example:
tblShirts
ShirtId int (PKey)
ColorId int (FKey tblColors)
SizeId int (FKey tblSizes)
StyleId int (FKey tblStyles)
Price money
QtyOnHand int
In this example tblColors, tblSizes and tblStyles are simple lookup tables. There's no need to create a linking table to resolve a many-to-many relationship.