❖ Mapping ER to SQL |
We have explored mapping ER designs to relational schemas
SQL schemas are essentially more detailed versions of relational schemas
The mapping is much the same, except that
❖ Reminder: SQL/Relational Model vs ER Model |
Correspondences between SQL/relational and ER data models:
❖ Mapping ER to SQL |
Some conventions that we use in mapping ER to SQL
table
TABLE
primary key
text
table_id
❖ Mapping Strong Entities |
An entity set E with atomic attributes a1, a2, ... an
maps to
A table R with attributes (columns) a1, a2, ... an
Example:
Note: the key is preserved in the mapping.
❖ Mapping N:M Relationships (cont) |
create table Customers ( custNo serial primary key, name text not null, address text -- don't need to know customer's address ); create table Accounts ( acctNo char(5) check (acctNo ~ '[A-Z]-[0-9]{3}'), title text not null, -- acctNos are like 'A-123' balance float default 0.0, primary key (acctNo) ); create table Owns ( customer_id integer references Customers(custNo), account_id char(5) references Accounts(acctNo), last_accessed timestamp, primary key (customer_id, account_id) );
❖ Mapping 1:N Relationships (cont) |
create table Branches (
branchNo serial primary key,
address text not null,
assets currency
);
create table Customers (
custNo serial primary key,
name text not null,
address text,
hasHome integer not null, -- total participation
joined date not null,
foreign key (hasHome) references Branches(branchNo)
);
hasHome
not null
❖ Mapping 1:1 Relationships (cont) |
create table Branches ( branchNo serial primary key, address text not null, assets currency -- a new branch ); -- may have no accounts create table Managers ( empNo serial primary key, name text not null, salary currency not null, -- when first employed, -- must have a salary manages integer not null, -- total participation foreign key (manages) references Branches(branchNo) );
If both entities have total participation, cannot express this in SQL
except by putting a (redundant) not null
❖ Mapping n-way Relationships |
Example:
A customer accesses one of their accounts at a specific ATM
❖ Mapping n-way Relationships (cont) |
create table Customers ( custNo serial primary key, ... ); create table Accounts ( acctNo char(5) ... primary key, ... ); create table ATMs ( atmID serial primary key, cash currency check (cash >= 0), location text not null ); create table Withdrawal ( customer_id integer references Customers(custNo), account_id char(5) references Accounts(acctNo), atm_id integer references ATMs(atmID), amount currency not null, when timestamp default now(), primary key (customer_id,account_id,atm_id) );
❖ Mapping Composite Attributes |
Composite attributes are mapped by concatenation or flattening.
Example:
❖ Mapping Composite Attributes (cont) |
-- Version 1: concatenated create table People ( ssn integer primary key, name text not null, address text not null ); -- Version 2: flattened create table People ( ssn integer primary key, given text not null, family text, number integer not null, street text not null, suburb text not null, pcode char(4) not null check (pcode ~ '[0-9]{4}') );
address
(number::text||' '||street||', '||suburb||' '||pcode)
Searching: suburb = 'Coogee'
address like '%Coogee%'
Sorting: order by family
❖ Mapping Multi-valued Attributes (MVAs) |
MVAs are mapped by a new table linking values to their entity.
Example:
❖ Mapping Multi-valued Attributes (MVAs) (cont) |
create table People ( ssn integer primary key, name text not null, birthday date ); create table FavColour ( person_id integer references People(ssn), colour text, primary key (person_id,colour) );
Note that colour
not null
❖ Mapping Subclasses |
Three different approaches to mapping subclasses to tables:
❖ Mapping Subclasses (cont) |
create table People ( ssn integer primary key, name text not null, address text ); create table Employees ( person_id integer primary key, salary currency not null, position text not null, foreign key (person_id) references People(ssn) ); create table Managers ( employee_id integer primary key, bonus currency, foreign key (employee_id) references Employees(person_id) );
❖ Mapping Subclasses (cont) |
create table People ( ssn integer primary key, name text not null, address text ); create table Employees ( ssn integer primary key, name text not null, address text salary currency not null, position text not null, foreign key (snn) references People(ssn) ); create table Managers ( ssn integer primary key, name text not null, address text salary currency not null, position text not null, bonus currency, foreign key (snn) references People(ssn) );
❖ Mapping Subclasses (cont) |
create table People ( ssn integer primary key, ptype char(1) not null check (ptype in ('P','E','M')), name text not null, address text salary currency, position text, bonus currency, constraint subclasses check ((ptype = 'P' and salary is null and position is null and bonus is null) or (ptype = 'E' and salary is not null and position is not null and bonus is null) or (ptype = 'M' and salary is not null and position is not null and bonus is not null)) );
❖ Mapping Subclasses (cont) |
Example:
Every employee is either permanent or casual, but not both.
❖ Mapping Subclasses (cont) |
ER-style mapping to SQL schema:
create table Employees ( empID serial primary key, name text not null, address text not null ); create table Permanents ( employee_id integer primary key, salary currency not null, foreign key (employee_id) references Employees(empID) ); create table Casuals ( employee_id integer primary key, pay_rate currency not null, foreign key (employee_id) references Employees(empID) );
Does not capture either participation or disjoint-ness constraints!
Would need to program a solution to this e.g web-form that requires user to enter both Employee and subclass info
Produced: 22 Sep 2020