I am currently working at a construction management software and I stepped into a problem (described below) when designing the schema for my database which contains four tables, for now, i.e employee, address, user and license.
The tables that created the confusion are employee and address; code provided down below.
In order to maintain the Physical integrity of my data, I did not store anything lexically derived from address, such as Address1, Address2, City, State, County etc in the table employee; since I subjectively considered that it would be better for attributes that do not uniquely identify a specific employee to make part of another table. Now my question arises:
Is it a good choice to use a GUID as the primary key for the address table?
If yes, is there any possibility that it may be a factor which prevents fast querying?
The reason why I have chosen to use a GUID as PK-indexing is that I was left with no options. EmployeeId from address does not offer me a solution since I can not have a field being PK as well as FK: see this.
CREATE TABLE employee(
employeeId INT
NOT NULL
CHECK(employeeId > 0),
firstname VARCHAR(20)
NOT NULL,
lastname VARCHAR(20)
NOT NULL,
sex VARCHAR(1)
NOT NULL,
birthdate DATE
NOT NULL,
addressId VARCHAR(30),
PRIMARY KEY(employeeId)
);
CREATE TABLE address(
addressId VARCHAR(30)
NOT NULL,
employeeId INT,
Address1 VARCHAR(120)
NOT NULL,
Address2 VARCHAR(120),
Address3 VARCHAR(120),
City VARCHAR(100)
NOT NULL,
State CHAR(2)
NOT NULL,
Country CHAR(2)
NOT NULL,
PostalCode VARCHAR(16)
NOT NULL,
PRIMARY KEY(addressId),
FOREIGN KEY(employeeId) REFERENCES employee(employeeId) ON DELETE SET NULL
);
ALTER TABLE employee
ADD FOREIGN KEY(addressId)
REFERENCES address(addressId)
ON DELETE SET NULL;
I would love to know if there are any other ways to create an appropriate relationship between employee and address without using GUID. Another way would be a specified (int) value, but in that case a disadvantage would be:
Introducing by mistake a FK != PK which will lead to a poor relationship between the tables.
EDIT:
Some of you suggested in the comments to change "UUID" indexing to AUTO_INCREMENT but the problem for me arises when I have to insert employees from my WPF-application.
The PK addressId from address will keep increasing on its own. What am I supposed to pass into the FK then to keep the relationship tight and correct then?
Should I create a variable of type int, let's say var i = 0 and every time I insert one employee -> increase that variable by one -> assign it to the FK or?
You'll want something like this in order to do a many-to-many association between employees and addresses (Address types will be like home, work, billing, travel, etc.). You can then create other entity tables to track associations between those entities and addresses as well. In the table employee_address, those columns will be foreign keys back to their relative tables.
As for using GUIDs vs INT for primary keys, numeric values read faster than string values on a JOIN. Depending on how large your data gets, you may need to switch from INT to BIGINT years down the road.
Also, give these people some space to enter their names. 20 characters is way too short, especially for last names.
employee
--------
employee_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
firstname VARCHAR(255) NOT NULL,
lastname VARCAHR(255) NOT NULL,
gender BIT NOT NULL,
birthdate DATE NOT NULL
address
---------
address_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
address1 VARCHAR(255),
address2 VARCHAR(255),
address3 VARCHAR(255),
city VARCHAR(255),
state CHAR(2),
country CHAR(2)
address_type
--------------
address_type_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
address_type VARCHAR(255)
employee_address
-----------------
employee_address_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
employee_id INT,
address_id INT,
address_type_id INT
Related
Hello I am new to MySQL and having trouble creating a table. It says that the types im using are not valid at their position with ')'.
Can someone tell me what is wrong with this code snippet?
create table CUSTOMER(
CustomerID int AUTO_INCREMENT,
LastName varchar,
FirstName varchar,
Address varchar,
City varchar,
State varchar,
ZIP number,
Phone number,
EmailAddress varchar,
constraint pk_cID primary key(CustomerID));
Your table should look like:
create table CUSTOMER(
CustomerID int not null AUTO_INCREMENT,
LastName varchar(100),
FirstName varchar(100),
Address varchar(100),
City varchar(100),
State varchar(100),
ZIP int,
Phone varchar(50),
EmailAddress varchar(100),
primary key(CustomerID)
);
number is not a datatype in MySQL
When you assign auto_increment it should be not null auto_increment
You don't need a constraint for primary key, just add primary key.
I don't think the best way of storing Phone numbers is int, you might have different formatting the best way is to treat numbers as addresses , so varchar would be better
I have three tables: property, person, and company. One property can only belong to either a person or a company. A person or a company can have more than one property.
My current database design is to include two foreign keys - person_id and company_id in property table, always with one of them null and the other not null. I'm just wondering is there any better way to design the database in this scenario?
CREATE TABLE person(
person_id int NOT NULL PRIMARY KEY,
name varchar(255)
);
CREATE TABLE company(
company_id int NOT NULL PRIMARY KEY,
name varchar(255)
);
CREATE TABLE property(
property_id int NOT NULL PRIMARY KEY,
name varchar(255),
person_id REFERENCES person,
company_id REFERENCES company
);
Create additional table CHECK constraint:
CREATE TABLE property(
property_id int NOT NULL PRIMARY KEY,
name varchar(255),
person_id REFERENCES person,
company_id REFERENCES company,
CHECK (person_id IS NULL + company_id IS NULL = 1)
);
This will forbid wrong values (both NULL or both NOT NULL).
PS. Two references presence is legal and safe itself.
Suppose i have a table customers having multiple fields. I am considering, three fields to be unique :date of birth, phone number, mail id. in order to create this table, the create script would be:
create table customers(
customer_id INT AUTO_INCREMENT,
first_name VARCHAR(255),
last_name VARCHAR(255),
address VARCHAR(255),
DOB datetime Not NULL,
phone_number int(10) NOT NULL,
email_address VARCHAR(255) NOT NULL,
PRIMARY KEY (customer_id),
UNIQUE KEY (customer_id,DOB,phone_number,email_address)
);
however i have noticed that unique key is declared with a name - UNIQUE KEY customer_id (customer_id,DOB,phone_number,email_address).
I need help in understanding why and when the unique constraint to be named, and what value would it add? Also what is the best practice for naming?
(Note:I do understand the concept of UNIQUE INDEX, but here i want to understand the naming of UNIQUE constraint)
Am i doing this correctly? I know it's super simply, but I am just now getting some DBA experience.
I have an Entity Table that is non static called Emps. The Emps table stores all the Employee personal information like phone numbers and so on. I then have a table called EmployeeOfflineTraining. This Table stores all Employees who are certified in Classroom training like Forklift.
Do i simply put a foreign key inside the EmployeeOfflineTraining table to assign training records to that employee ID?
Emps
(Phone, Agency, Name)
EmployeeOffLineTraining
(GpcScore, Forklift Score, ForklifeCertified, EmpsId)
I would create an indirection table that maps TrainingId to EmployeeOfflineTraining as well. This gives you flexibility in case you need to introduce multiple training types -- you can simply add a row to the Training table rather than having to alter the EmployeeOFflineTraining table.
You may also consider creating an Agency and EmployeeAgency table as well in the same vein.
CREATE TABLE Emps (
empId int unsigned not null auto_increment primary key,
phone varchar(255),
agency varchar(255),
name varchar(255)
);
CREATE TABLE Training (
trainingId int unsigned not null auto_increment primary key,
name varchar(255)
);
CREATE TABLE EmployeeOfflineTraining (
eotId int unsigned not null auto_increment primary key,
empId int unsigned not null,
trainingId int unsigned not null,
score smallint unsigned,
certifiedDate datetime,
foreign key (empId) references Emps(empId),
foreign key (trainingId) references Training(trainingId)
);
Yes.Wikipedia Entry On DB Normilzation What you are looking for is called Databse Normilzation
Employees
EmployeeID PrimaryKey
Phone
EmployeeName
AgencyId
Agencies
AgencyId PrimaryKey
AgencyName
EmployeeOfflineTraining
EMployeeOfflineTrainingId PrimaryKey
EmployeeId ForiegnKey to Employee Table
GpcSocre
ForkliftScore
ForkliftCertified
Edit
As pointed out be Sean Lange The OfflineTraining Table has major problems which are not addressed in this answer.
this question is applicable on different RDBMS: MySQL and SQL Server
I've been searching for this all night and I can't find it on the net. My problem is all about uniqueness and foreign keys. Consider the following schema:
CREATE TABLE Male
(
StudentID INT,
FirstName VARCHAR(20) NOT NULL,
MiddleName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
-- other columns ...
CONSTRAINT male_PK PRIMARY KEY (StudentID),
CONSTRAINT male_UQ UNIQUE (FirstName, MiddleName, LastName)
);
CREATE TABLE Female
(
StudentID INT,
FirstName VARCHAR(20) NOT NULL,
MiddleName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
-- other columns ...
CONSTRAINT Female_PK PRIMARY KEY (StudentID),
CONSTRAINT Female_UQ UNIQUE (FirstName, MiddleName, LastName)
);
CREATE TABLE ClassList
(
ClassID INT,
Name VARCHAR(30),
ClassYear INT,
-- other columns ...
CONSTRAINT ClassList_PK PRIMARY KEY (ClassID),
CONSTRAINT ClassList_UQ UNIQUE (Name, ClassYear)
);
The reason why table Male and Female are separated is because they are maintained by different sql accounts.
The problem now is the Association Class.
CREATE Student_Class
(
SudentID INT,
ClassID INT,
CONSTRAINT tb_UQ UNIQUE (StudentID, ClassID)
)
So my questions are:
How can I set the uniqueness of the StudentID from both tables Male and Female. I can't find that on the net.
How can I enforce Foreign Key constraints in which the value column of the association class table come from two tables: Male and Female?
Suggestions are also Accepted.
Thank You
This is why attribute splitting is bad - it starts "infecting" the other tables in odd ways.
You can have:
CREATE Student_Class
(
MaleStudentID INT NULL,
FemaleStudentID INT NULL,
ClassID INT NOT NULL,
CONSTRAINT tb_UQ UNIQUE (MaleStudentID, FemaleStudentID, ClassID)
)
Since MySQL, so far as I'm aware, doesn't support CHECK constraints, you'll also have to create a trigger that ensures only one, and exactly one, of MaleStudentID and FemaleStudentID is NOT NULL.
You can now apply your foreign key constraints in an obvious manner.
For SQL Server, you would have a check constraint:
ALTER TABLE Student_Class ADD CONSTRAINT CK_Students_Nullability CHECK (
(MaleStudentID is null and FemaleStudentID is not null) or
(MaleStudentID is not null and FemaleStudentID is null)
)
I don't think it's a great idea to let user privileges dictate your schema but if you have to then I think the idea mentioned by HerpaMoTeH is a good one. A third table with id, gender and with the id used as an FK in the gender specific tables and student_class.
Another solution is to just split your student_class table into two:
male_student_class and female_student_class
Alternatively you could create 2 sets of stored procedures (male and female) for CRUD operations on a single student table. Then you would deny priviliges to the actual table for your users but grant them access to the appropriate set of stored procedures. Your schema would be simplified to:
CREATE TABLE Student
(
StudentID INT,
GenderId INT,
FirstName VARCHAR(20) NOT NULL,
MiddleName VARCHAR(20) NOT NULL,
LastName VARCHAR(20) NOT NULL,
-- other columns ...
);
CREATE Student_Class
(
SudentID INT,
ClassID INT,
CONSTRAINT tb_UQ UNIQUE (StudentID, ClassID)
)
You can:
Set a range for StudentID to identify Male / Female. For example 10000 to 19999 for male and 20000 to 29999 for female
Alternately, you can add a redundant column "Sex" in both tables, with M for male and F for female and make that part of the reference
Raj