I'm building a diagram on LucidChart for a Brewery that sells and makes beer in 1 location. I watched some videos on how to design an ER model. Wondering if this is correct or if I made any mistakes. Also what exactly is "mapping" for when talking about ER models?
Here is my ER model:
Also Cardinality Legend I went off of from LucidChart:
what exactly is "mapping" for when talking about ER models?
Within the context of a data model, the term "mapping" is a name for the process of converting a data model into the SQL DDL that can then be used to create a database schema in a database management system such as MySQL, SQL Server, Oracle and so on.
To the best of my knowledge, you can't "map" with tools such as Visio and LucidChart because these tools are not designed for data modeling. They are designed to mechanise the process of drawing diagrams. (A proper data model contains a lot more than pictures)
As an example, I used your ER diagram to design an object-role model using the free NORMA tool.The following diagrams show:
The object-role model
The logical model (It took a few milliseconds to generate the logical model from the object-role model.)
The SQL DDL that I "mapped" from the object-role model (It took a few seconds to map the object-role model into SQL DDL.)
I use SQL Server Management Studio so I can copy and paste the T-SQL version of the DDL into the "New Query" window and generate the database tables in a few seconds.
This is the object-role model (split into pages)
This is the logical model (auto generated) Note that unlike your model, there is only one "Address" table in the logical model.
This is the SQL DDL for MySQL Server (auto generated)
CREATE TABLE Brewery
(
breweryNr INT NOT NULL,
addressNr INT NOT NULL,
breweryName CHAR(63) NOT NULL,
CONSTRAINT Brewery_PK PRIMARY KEY(breweryNr)
);
CREATE TABLE Address
(
addressNr INT NOT NULL,
country CHAR(63) NOT NULL,
street CHAR(63) NOT NULL,
town CHAR(63) NOT NULL,
zipCode CHAR(63) NOT NULL,
CONSTRAINT Address_PK PRIMARY KEY(addressNr)
);
CREATE TABLE Beer
(
beerType CHAR(63) NOT NULL,
alcoholPercent INT NOT NULL,
beerAmountLitres CHAR(63) NOT NULL,
beerID CHAR(63) NOT NULL,
beerPrice CHAR(63) NOT NULL,
kegNr INT NOT NULL,
CONSTRAINT Beer_PK PRIMARY KEY(beerType)
);
CREATE TABLE BreweryMakesBeer
(
beerType CHAR(63) NOT NULL,
breweryNr INT NOT NULL,
CONSTRAINT BreweryMakesBeer_PK PRIMARY KEY(breweryNr, beerType)
);
CREATE TABLE Keg
(
kegNr INT NOT NULL,
kegState CHAR(63) NOT NULL,
CONSTRAINT Keg_PK PRIMARY KEY(kegNr)
);
CREATE TABLE Employee
(
employeeNr INT NOT NULL,
addressNr INT NOT NULL,
birthDate INT NOT NULL,
breweryNr INT NOT NULL,
firstName CHAR(63) NOT NULL,
lastName CHAR(63) NOT NULL,
salary DECIMAL(6,4) NOT NULL,
SSN CHAR(63) NOT NULL,
middleInt CHAR(63),
CONSTRAINT Employee_PK PRIMARY KEY(employeeNr)
);
CREATE TABLE Distributor
(
distributorNr INT NOT NULL,
brewingIngredientNr INT NOT NULL,
CONSTRAINT Distributor_PK PRIMARY KEY(distributorNr)
);
CREATE TABLE BrewingIngredient
(
brewingIngredientNr INT NOT NULL,
ingredientName CHAR(63) NOT NULL,
CONSTRAINT BrewingIngredient_PK PRIMARY KEY(brewingIngredientNr)
);
CREATE TABLE IngredientSupplier
(
ingredientSupplierNr INT NOT NULL,
addressNr INT NOT NULL,
CONSTRAINT IngredientSupplier_PK PRIMARY KEY(ingredientSupplierNr)
);
CREATE TABLE IngredientSupply
(
brewingIngredientNr INT NOT NULL,
ingredientSupplierNr INT NOT NULL,
CONSTRAINT IngredientSupply_PK PRIMARY KEY(brewingIngredientNr, ingredientSupplierNr)
);
ALTER TABLE Brewery ADD CONSTRAINT Brewery_FK FOREIGN KEY (addressNr) REFERENCES Address (addressNr) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE Beer ADD CONSTRAINT Beer_FK FOREIGN KEY (kegNr) REFERENCES Keg (kegNr) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE BreweryMakesBeer ADD CONSTRAINT BreweryMakesBeer_FK1 FOREIGN KEY (breweryNr) REFERENCES Brewery (breweryNr) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE BreweryMakesBeer ADD CONSTRAINT BreweryMakesBeer_FK2 FOREIGN KEY (beerType) REFERENCES Beer (beerType) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE Employee ADD CONSTRAINT Employee_FK1 FOREIGN KEY (breweryNr) REFERENCES Brewery (breweryNr) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE Employee ADD CONSTRAINT Employee_FK2 FOREIGN KEY (addressNr) REFERENCES Address (addressNr) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE Distributor ADD CONSTRAINT Distributor_FK FOREIGN KEY (brewingIngredientNr) REFERENCES BrewingIngredient (brewingIngredientNr) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE IngredientSupplier ADD CONSTRAINT IngredientSupplier_FK FOREIGN KEY (addressNr) REFERENCES Address (addressNr) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE IngredientSupply ADD CONSTRAINT IngredientSupply_FK1 FOREIGN KEY (brewingIngredientNr) REFERENCES BrewingIngredient (brewingIngredientNr) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE IngredientSupply ADD CONSTRAINT IngredientSupply_FK2 FOREIGN KEY (ingredientSupplierNr) REFERENCES IngredientSupplier (ingredientSupplierNr) ON DELETE RESTRICT ON UPDATE RESTRICT;
Related
I can not add a referential constraint, both tables has the two columns id and version as primary key. I will only check the integrity that the row is existing without checking version.
CREATE TABLE TABLEE
(ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
PRIMARY KEY (ID , VERSION);
CREATE TABLE CHAIR
(ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
ID_TABLEE INTEGER,
PRIMARY KEY (ID , VERSION);
ALTER Chair
ADD constraint MYC FOREIGN KEY (ID)
REFERENCES TABLEE (ID)
ON DELETE RESTRICT
Got this error
[Code: -573, SQL State: 42890] A column list specified in the references clause of constraint "MYC " does not identify a unique constraint of the parent table or nickname "TABLEE".. SQLCODE=-573, SQLSTATE=42890, DRIVER=4.28.11
The problem here is that Tablee its primary key consists of two columns id and version. But the integrity check should only be made on the referenced id, not version.
To establish a foreign key on a table the referenced column needs to:
Be a primary key on the other table.
...or at least act as one.
Since you already have a primary key on the referenced table, you can use the second approach and add a UNIQUE and NOT NULL constraints on ID.
For example:
CREATE TABLE TABLEE (
ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
PRIMARY KEY (ID , VERSION),
constraint uq1 unique (id) -- added UNIQUE constraint on ID
);
CREATE TABLE CHAIR (
ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
ID_TABLEE INTEGER,
PRIMARY KEY (ID , VERSION)
);
ALTER table Chair
ADD constraint MYC FOREIGN KEY (ID)
REFERENCES TABLEE (ID)
ON DELETE RESTRICT;
See running example at db<>fiddle.
Note: If you want ID to have repeated values over the table, then ID is not a key, and cannot be referenced as one.
I'm trying to transform my MySQL design to PostgreSQL but when I try to create the table "index":
CREATE TABLE "model1"."index" (
"id_index" INT GENERATED ALWAYS AS IDENTITY ,
"index_name" VARCHAR(5) NOT NULL,
"index_type_id_index_type" INT NOT NULL,
"index_provider_id_index_provider" INT NOT NULL,
"miseq" VARCHAR(45) NOT NULL,
"nextseq" VARCHAR(45) NOT NULL,
PRIMARY KEY ("id_index"),
CONSTRAINT "fk_index_index_type"
FOREIGN KEY ("index_type_id_index_type")
REFERENCES "model1"."index_type" ("id_index_type")
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT "fk_index_index_provider"
FOREIGN KEY ("index_provider_id_index_provider")
REFERENCES "model1"."index_provider" ("id_index_provider")
ON DELETE NO ACTION
ON UPDATE NO ACTION);
I got this error: ERROR: there is no unique constraint matching given keys for referenced table "index".
The two tables containing the foreign keys were created before the "index" table:
CREATE TABLE "model1"."index_type" (
"id_index_type" INT GENERATED ALWAYS AS IDENTITY ,
"name" VARCHAR(3) NOT NULL,
PRIMARY KEY ("id_index_type"));
CREATE TABLE "model1"."index_provider" (
"id_index_provider" INT GENERATED ALWAYS AS IDENTITY ,
"name" VARCHAR(40) NOT NULL,
PRIMARY KEY ("id_index_provider"));
Solved. The error was in another table as #a_horse_with_no_name suggested.
cannot add foreign key constraint to table
create table users
(
user_id int auto_increment primary key not null,
username varchar(50) unique null ,
email varchar(50) unique ,
passwords varchar(50) not null,
login_status boolean not null
);
create table category (
category_id int primary key not null,
category_name varchar(50) not null
);
create table answers (
id_answer int auto_increment primary key not null,
answer boolean not null
);
create table questions (
question_id int primary key not null,
category_name varchar(50) not null,
content varchar(50) not null ,
foreign key (category_name) references category (category_name)
);
You get this error because there's no index on category_name in the category table. Change that CREATE statement as follows:
create table category (
category_id int primary key not null,
category_name varchar(50) not null,
KEY category_name_index (category_name)
);
From the docs (8.0 version, but the statement is true for older versions):
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later, if you create another index that can be used to enforce the foreign key constraint. index_name, if given, is used as described previously.
Also, you're using a varchar(50) as your foreign key, which is not usually a great idea for a variety of reasons. You probably want to use a numeric value, such as category_id, instead.
I am struggling with foreign keys in my DB, possibly it has something to do with inheritance?
So here's the basic setup:
-- table address
CREATE TABLE address
(
pk_address serial NOT NULL,
fk_gadmid_0 integer NOT NULL, -- this table already exists, no problem here
street character varying(100),
zip character varying(10),
city character varying(50),
public boolean,
CONSTRAINT address_primarykey PRIMARY KEY (pk_address),
CONSTRAINT gadmid_0_primarykey FOREIGN KEY (fk_gadmid_0)
REFERENCES adm0 (gadmid_0) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE address OWNER TO postgres;
-- table stakeholder (parent)
CREATE TABLE stakeholder
(
pk_stakeholder integer DEFAULT nextval('common_stakeholder_seq') NOT NULL,
fk_stakeholder_type integer NOT NULL, -- this table also exists, no problem here
name character varying(255) NOT NULL,
CONSTRAINT stakeholder_primarykey PRIMARY KEY (pk_stakeholder),
CONSTRAINT stakeholder_fk_stakeholder_type FOREIGN KEY (fk_stakeholder_type)
REFERENCES stakeholder_type (pk_stakeholder_type) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE stakeholder OWNER TO postgres;
-- table individual (child of stakeholder)
CREATE TABLE individual
(
firstname character varying(50),
fk_title integer, -- this table also exists, no problem here
email1 character varying (100),
email2 character varying (100),
phone1 character varying (50),
phone2 character varying (50),
CONSTRAINT individual_primarykey PRIMARY KEY (pk_stakeholder),
CONSTRAINT title_foreignkey FOREIGN KEY (fk_title)
REFERENCES title (pk_title) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
) INHERITS (stakeholder)
WITH (
OIDS=FALSE
);
ALTER TABLE individual OWNER TO postgres;
-- link between stakeholder and address
CREATE TABLE l_stakeholder_address
(
pk_l_stakeholder_address serial NOT NULL,
fk_stakeholder integer NOT NULL REFERENCES stakeholder,
fk_address integer NOT NULL REFERENCES address,
CONSTRAINT l_stakeholder_address_primarykey PRIMARY KEY (pk_l_stakeholder_address),
CONSTRAINT l_stakeholder_address_fk_stakeholder FOREIGN KEY (fk_stakeholder)
REFERENCES stakeholder (pk_stakeholder) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION,
CONSTRAINT l_stakeholder_address_fk_address FOREIGN KEY (fk_address)
REFERENCES address (pk_address) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE l_stakeholder_address OWNER TO postgres;
So far, no problem. Then I tried to add some values:
INSERT INTO individual (pk_stakeholder, fk_stakeholder_type, name, firstname, fk_title, email1, email2, phone1, phone2)
VALUES (1, 8, 'Lastname', 'Firstname', 1, 'me#you.com', '', '', '');
INSERT INTO address (pk_address, fk_gadmid_0, street, zip, city, public)
VALUES (1, 126, 'Address', '', 'City', FALSE);
INSERT INTO l_stakeholder_address (pk_l_stakeholder_address, fk_stakeholder, fk_address)
VALUES (DEFAULT, 1, 1);
And finally I end up having an error (SQL state 23503) saying that the key (fk_stakeholder)=(1) is not existing in table "stakeholder".
The first 2 inserts are fine, I can see them in the databases:
stakeholder:
pk_stakeholder | ...
----------------------
1 | ...
address:
pk_address | ...
--------------------
1 | ...
What am I doing wrong? I must admit that I am rather new to PostgreSQL (using 8.4) but I'm not even sure if that is an issue of PG at all, maybe I'm just lacking some basic database design understandings ...
Either way, by now I tried pretty much everything I could think of, I also tried to make the FK deferrable as in PostgreSQL : Transaction and foreign key problem but somehow that doesn't work either.
You can work around it using additional table individual_pks (individual_pk integer primary key) with all primary keys from both parent and child, which will be maintained using triggers (very simple — insert to individual_pks on insert, delete from it on delete, update it on update, if it changes individual_pk).
Then you point foreign keys to this additional table instead of a child. There'll be some small performance hit, but only when adding/deleting rows.
Or forget inheritance and do it the old way - simply one table with some nullable columns.
Your analysis is exactly right: It's because of the inheritance. When checking the foreign key, child tables are not considered.
In general, inheritance and foreign keys don't mix well in PostgreSQL. A major problem is that you can't have unique constraints across tables.
Reference
I've got a problem I can't figure out how to express with CTP5 of Code First and EF4.
EDIT: Added my old schema at the bottom that I'd like to replicate through CF
Here's my specific scenario:
A Team is an abstract concept; it should exist with a specific set of players, in a specific division, in a specific season.
A concrete example of this in action from the NFL:
1996 (season) AFC Central (division) Houston Oilers (team)
1997 (season) AFC Central (division) Tennessee Oilers (team)
1999 (season) AFC Central (division) Tennessee Titans (team)
2002 (season) AFC South (division) Tennessee Titans (team)
These are all the same team. I want to be able to do the following:
// Titans team id = 17
var myTeam = myContext.Teams.Single(t => t.Id == 17)
// display players
foreach (var p in myTeam.Seasons[1999].Players)
{
// Do something with the p here
}
// Display current division
Response.Write(myTeam.Seasons[2002].Division.Name);
I'm not sure of the specific query syntax within an ICollection member variable of myTeam.Seasons, but the concept should be the same none the less.
Can anyone shed some light on how you'd express this concept through CF in EF4 CF CTP5?
How would you express this through Code First?
Current SQL tables
CREATE TABLE dbo.Season
(
Id INT IDENTITY(1,1) NOT NULL,
LeagueId INT NOT NULL,
[Name] NVARCHAR(50) NOT NULL,
[Year] CHAR(4) NOT NULL,
PrevSeasonId INT NULL
) ON [PRIMARY];
// Primary key
ALTER TABLE dbo.Season WITH NOCHECK ADD
CONSTRAINT PK_Season PRIMARY KEY NONCLUSTERED (Id) ON [PRIMARY];
CREATE TABLE dbo.Division
(
Id INT IDENTITY(1,1) NOT NULL,
DefaultName NVARCHAR(50) NOT NULL
) ON [PRIMARY];
// Primary key
ALTER TABLE dbo.Division WITH NOCHECK ADD
CONSTRAINT PK_Division PRIMARY KEY NONCLUSTERED (Id) ON [PRIMARY];
// Key Relation Table
CREATE TABLE dbo.DivisionsInSeason
(
DivisionId INT NOT NULL,
SeasonId INT NOT NULL,
DefaultName NVARCHAR(50) NOT NULL,
Commissioner UNIQUEIDENTIFIER NOT NULL,
ParentDivId INT NULL
) ON [PRIMARY];
// Primary Key
ALTER TABLE dbo.DivisionsInSeason WITH NOCHECK ADD
CONSTRAINT PK_DivisionsInSeason PRIMARY KEY NONCLUSTERED (DivisionId, SeasonId) ON [PRIMARY] ;
// Foreign Keys
ALTER TABLE dbo.DivisionsInSeason WITH CHECK ADD
CONSTRAINT FK_DivisionsInSeason_Division FOREIGN KEY(DivisionId) REFERENCES dbo.Division(Id),
CONSTRAINT FK_DivisionsInSeason_Season FOREIGN KEY(SeasonId) REFERENCES dbo.Season(Id),
CONSTRAINT FK_DivisionsInSeason_User FOREIGN KEY(Commissioner) REFERENCES dbo.[User](Id);
CREATE TABLE dbo.Team
(
Id INT IDENTITY(1,1) NOT NULL,
DefaultName NVARCHAR(50) NOT NULL,
DefShortName NCHAR(3) NULL
) ON [PRIMARY];
// Primary key
ALTER TABLE dbo.Team WITH NOCHECK ADD
CONSTRAINT PK_Team PRIMARY KEY NONCLUSTERED (Id) ON [PRIMARY] ;
// Key relationship table
CREATE TABLE dbo.TeamsInDivision
(
TeamId INT NOT NULL,
DivisionId INT NOT NULL,
SeasonId INT NOT NULL,
GeneralManager UNIQUEIDENTIFIER NOT NULL,
Name NVARCHAR(50) NOT NULL,
ShortName NCHAR(3) NULL
) ON [PRIMARY];
// Check Constraints
ALTER TABLE dbo.TeamsInDivision ADD
CONSTRAINT PK_TeamsInDivision PRIMARY KEY NONCLUSTERED (TeamId, DivisionId, SeasonId) ON [PRIMARY];
// Foreign Keys
ALTER TABLE dbo.TeamsInDivision WITH CHECK ADD
CONSTRAINT FK_TeamsInDivision_Team FOREIGN KEY(TeamId) REFERENCES dbo.Team(Id),
CONSTRAINT FK_TeamsInDivision_Division FOREIGN KEY(DivisionId) REFERENCES dbo.Division(Id),
CONSTRAINT FK_TeamsInDivision_Season FOREIGN KEY(SeasonId) REFERENCES dbo.Season(Id),
CONSTRAINT FK_TeamsInDivision_User FOREIGN KEY(GeneralManager) REFERENCES dbo.[User](Id);
Maybe this could be usefull
http://blogs.microsoft.co.il/blogs/gilf/archive/2011/08/01/creating-a-many-to-many-mapping-using-code-first.aspx