I am a very beginner in MYSQL and I am trying to use CHECK for EmployeeID is in the format of E### where "#" is the number(int). ANd the DOB that is eneterd should be 16 years or older from current date. Here is the code for the table. Thanks for help!
Create table Employee(
EmployeeID varchar(200) not null primary key,
DOB date,
##Check (DOB <= CURRENT_DATE - interval '16' year),
FirstName varchar(200),
MiddleName varchar(200),
LastName varchar(200),
Address varchar(255),
StartDate date,
Gender varchar(100)
);
I would use a regular expression to confirm the validity of the EmployeeID, such as this :-
EmployeeID varchar(200) not null primary key CHECK EmployeeID REGEXP 'E\d{3}',
Other answers covered using the check constraints.
However, if it's always going to start with an 'E', do you need to store the 'E'? Can you store just the integer and add the E later? An integer primary key is simpler, faster, smaller, and more robust.
Use a generated column to provide the ID with the E on it.
create table Employee (
-- No check required, it's an integer by definition.
-- Takes less storage to store and index.
ID integer primary key,
-- A generated virtual column (takes no storage space)
EmployeeID varchar(255) as (concat('E', id)) virtual
);
insert into Employee (id) values (1), (23), (456);
select * from Employee;
ID EmployeeID
1 E1
23 E23
456 E456
select * from Employee where EmployeeID = 'E456';
ID EmployeeID
456 E456
Try it.
Related
I'm looking for a way to create a query that gives me the list of people who were born on the same day (the data is in two different tables).
All ideas are welcome. ( I use MySQL)
SQL code :
https://pastebin.com/StNggaYg
CREATE TABLE Professeurs(
ID_Professeur Int Auto_increment NOT NULL ,
Nom_Professeur Varchar (50) NOT NULL ,
Prenom_Professeur Varchar (50) NOT NULL ,
Ville_de_naissance_P Varchar (50) NOT NULL ,
Date_de_naissance_P Date NOT NULL ,
Professeur_Principal Bool NOT NULL
,CONSTRAINT Professeurs_PK PRIMARY KEY (ID_Professeur)
)ENGINE=InnoDB;
#------------------------------------------------------------
# Table: Classes
#------------------------------------------------------------
CREATE TABLE Classes(
ID_Classes Int Auto_increment NOT NULL ,
Lettre_classe Char (5) NOT NULL ,
ID_Professeur Int NOT NULL
,CONSTRAINT Classes_PK PRIMARY KEY (ID_Classes)
,CONSTRAINT Classes_Professeurs_FK FOREIGN KEY (ID_Professeur) REFERENCES Professeurs(ID_Professeur)
)ENGINE=InnoDB;
#------------------------------------------------------------
# Table: Elèves
#------------------------------------------------------------
CREATE TABLE Eleves(
ID_Eleve Int Auto_increment NOT NULL ,
Nom_eleve Varchar (50) NOT NULL ,
Prenom_eleve Varchar (50) NOT NULL ,
Ville_de_naissance_E Varchar (50) NOT NULL ,
Date_de_naissance_E Date NOT NULL ,
ID_Classes Int NOT NULL
,CONSTRAINT Eleves_PK PRIMARY KEY (ID_Eleve)
,CONSTRAINT Eleves_Classes_FK FOREIGN KEY (ID_Classes) REFERENCES Classes(ID_Classes)
)ENGINE=InnoDB;
The column :
Date_de_naissance_E Date NOT NULL ,
Date_de_naissance_P Date NOT NULL ,
First, you would have to get the results of BOTH tables dates via a UNION to find what dates have more than one instance. Its possible to have two teachers with same date, two students with same date, OR a teacher AND student have same date. Once that is done, then you can join back to the respective original source to grab the names.
To simplify the query from rewriting it twice nested within itself, I will use CTE (common table expression). It allows you to write a query that will be used multiple times allowing simple alias name to be used in a subsequent query.
Below is the CTE via "With AllPeople as". This select is the query used in the second half. Notice I am getting ID, name, birth date and also a type "P" as Professeur and "E" as Eleves for the person type. First time through I am getting a count where a given birthdate occurs more than once. THEN, re-join to the same AllPeople again that had that date found as a common birth date.
with AllPeople as
( select
'P' personType,
p.ID_Professeur personID,
p.Nom_Professeur personName,
Date_Format( p.Date_de_naissance_P, "%M %d" ) commonDate
from
Professeurs p
union all
select
'E' personType,
e.ID_Eleve personID,
e.nom_eleve personName,
Date_Format( e.Date_de_naissance_E, "%M %d" ) commonDate
from
Eleves e
)
select
who.PersonType,
who.PersonID,
who.PersonName,
BornOnSameDay.commonDate
from
(select
commonDate
from
AllPeople
group by
commonDate
having
count(*) > 1 ) BornOnSameDay
JOIN
AllPeople Who
on BornOnSameDay.commonDate = Who.commonDate
order by
BornOnSameDay.commonDate,
who.PersonName
Now, you also provided a class table of which teachers were teaching what class, and if a student was in a particular class. If your intention was to find out which classes has a student with the same birthdate as the professor teaching it, that would be a different query.
Please advise on which you meant. The one I have provided is ANY teacher having a same birthday as ANY other teacher OR student. And likewise could be two students having the same birth date.
You can use the GROUP_CONCAT function:
SELECT date_format(birthdate,"%d %b") AS birthday, GROUP_CONCAT(person_name) AS people
FROM persons
GROUP BY MONTH(birthdate), DATE(birthdate)
I am building a database for my website. I have a schema here : enrolin.in/download.png
Introduction to website:
It collects data from students on behalf of colleges.
Now what I have done in database is that I have created a UDT-where data that is fixed to a student is stored. and CST-where data that can change with every new course is stored.
I am very new to database design, so please have a look at the database design and advice me where i can improve. I want it to be perfect so that there are no complications/limitations with database in future
NOTES:
There is not just for one college. It is like a platform where different colleges can add their courses. Every college has different courses with different subjects etc. There can be many CST's, may be a separate CST for every new course. Plus I am not sure about the way I am storing course data , I mean CST and UDT. Every college will have access to the data of students which have applied for a course under that college and every student will have access to data to his previously filled form data,status etc.
Thanks in advance. If anything is unclear, please ask in comments.
Update : -- tables
-- Table CST
CREATE TABLE CST (
cst_id int NOT NULL ,
rollno int NOT NULL ,
semester int NOT NULL ,
CONSTRAINT CST_pk PRIMARY KEY (cst_id)
);
-- Table UDT
CREATE TABLE UDT (
udt_id int NOT NULL ,
id int NOT NULL ,
name varchar(255) NOT NULL ,
gender varchar(255) NOT NULL ,
fatherame varchar(255) NOT NULL ,
mothername varchar(255) NOT NULL ,
dob date NOT NULL ,
signature binary(255) NOT NULL ,
CONSTRAINT UDT_pk PRIMARY KEY (udt_id)
);
-- Table address
CREATE TABLE address (
address_id int NOT NULL ,
id int NOT NULL ,
add_name varchar(255) NOT NULL ,
add_street varchar(255) NOT NULL ,
city varchar(255) NOT NULL ,
state varchar(255) NOT NULL ,
country varchar(255) NOT NULL ,
pin int NOT NULL ,
CONSTRAINT address_pk PRIMARY KEY (address_id)
);
-- Table courses
CREATE TABLE courses (
course_id int NOT NULL ,
course_name varchar(255) NOT NULL ,
CONSTRAINT courses_pk PRIMARY KEY (course_id)
);
-- Table phones
CREATE TABLE phones (
phone_id int NOT NULL ,
id int NOT NULL ,
phone int NOT NULL ,
CONSTRAINT phones_pk PRIMARY KEY (phone_id)
);
-- Table photos
CREATE TABLE photos (
photo_id int NOT NULL ,
id int NOT NULL ,
photo binary(255) NOT NULL ,
CONSTRAINT photos_pk PRIMARY KEY (photo_id)
);
-- Table sub_trans
CREATE TABLE sub_trans (
sub_trans_id int NOT NULL ,
transactions_t_id int NOT NULL ,
subjects_sub_id int NOT NULL ,
CONSTRAINT sub_trans_pk PRIMARY KEY (sub_trans_id)
);
-- Table subjects
CREATE TABLE subjects (
sub_id int NOT NULL ,
course_id int NOT NULL ,
subjectname varchar(255) NOT NULL ,
CONSTRAINT subjects_pk PRIMARY KEY (sub_id)
);
-- Table transactions
CREATE TABLE transactions (
t_id int NOT NULL ,
id int NOT NULL ,
course_id int NOT NULL ,
p_status int NOT NULL DEFAULT 0 ,
phones_phone_id int NOT NULL ,
UDT_udt_id int NOT NULL ,
photos_photo_id int NOT NULL ,
address_address_id int NOT NULL ,
CST_cst_id int NOT NULL ,
CONSTRAINT transactions_pk PRIMARY KEY (t_id)
);
-- Table users
CREATE TABLE users (
id int NOT NULL ,
name varchar(255) NOT NULL ,
email varchar(255) NOT NULL ,
password int NOT NULL ,
CONSTRAINT users_pk PRIMARY KEY (id)
);
`
UDT:
Typo fathername. UDT has an FK to what? Users? Slim down the varchar size in UDT. Sure you want a single column for name? Ok, at least document that you chose to not have more than 2 parents. Otherwise you need another table.
Users:
Passwords run thru a hash function won't be ints and user needs a Salt for optimal security. Imho.
awaiting more clarification below
There is zero purpose of UDT and users both existing. Pick one, pickup lost fields from one you are ditching.
Even hypothetically if it wasn't 1:1 name would denomalize the database.
phones:
Your columns for phones need to be described. Also can a user have more than 1 phone (if so, phoneType varchar(10) or int code? )
Also I would go like varchar(30) on phone value not an int.
Addresses:
Same deal as phones. Can a user have more than one? PostalCode pin should be varchar
Transactions:
This seems to be the hub of your schema. All of your transactions hinge on FKs to data that may have subsequently changed. I see RISK in that. Older transaction could get skewed results for lookups. There are easy ways to fix this issue if you even see it as one. Same goes for courses. What if History 101's id stays the same but next semester that id is Early Roman Empire? Just things to think about.
Lastly the documented tables have no FK relationships shown.
I have the following table, where bookings can be made
CREATE TABLE booking (
bookingID INT UNSIGNED NOT NULL AUTO_INCREMENT,
customerID INT,
runID INT,
startDate DATETIME,
endDate DATETIME,
dateBookedOn TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (bookingID),
INDEX idx_start (startDate),
INDEX idx_end (endDate),
FOREIGN KEY (runID) REFERENCES RUn(RunID),
FOREIGN KEY (customerID) REFERENCES customer(CustomerID)
)
Then i have a run table
CREATE TABLE run
(
RunID INT UNSIGNED NOT NULL AUTO_INCREMENT,
RunName VARCHAR(15),
PricePerNight DECIMAL(3,2),
primary key (RunID)
);
I am querying the run table to get all runID's that do not lie between two dates in the booking table, as follows.
SELECT *
FROM run
WHERE Runid NOT IN (SELECT RunID
FROM booking
WHERE CAST(startDate AS DATE) >= '2015-07-19' AND
CAST(endDate AS DATE) <= '2015-07-25');
How would I change the query to select runID's that don't have ANY dates between them, if the dates overlap with query dates they are included in result set.
ie if a new booking had a startDate 2015-07-15 and a endDate 2015-07-21 then it will still show in the queries result set.
Your query does what you want, but might be a bit slow: Avoid NOT IN if you can. This should do the same but is just faster:
SELECT a.*
FROM run a
LEFT JOIN booking b ON a.runID=b.runID
AND startDate>= '2015-07-19' AND endDate<= '2015-07-25'
WHERE b.runID IS NULL;
Also avoid casting your data from your database: If you want/have to cast anything, cast your variables: Casting your variable=1 value cast, casting the data from your database is N values cast, plus that indexes can not be used anymore.
I need to auto_increment the primary key in a mysql database using a trigger. Unfortunately, I am not quite sure how to do this. In the sample code I have provided, I need the employee table primary key to auto_increment beginning with an empty table and a starting value of 200. Then, I need each new insert to increment by 1.Thanks for looking and I hope you are able to help me.
CREATE TABLE department (
dept_name VARCHAR(50) NOT NULL Primary Key
);
CREATE TABLE employee (
emp_id INT(6) unsigned Default 0 Not NULL
, last_name VARCHAR(25) NOT NULL
, first_name VARCHAR(40) NOT NULL
, dept_name VARCHAR(50) NOT NULL
, PRIMARY KEY(emp_id, dept_name)
, FOREIGN KEY(dept_name) REFERENCES department (dept_name)
);
There are several things you need to do:
Declare the emp_id column as AUTO_INCREMENT;
Set the value of AUTO_INCREMENT property of the table to 200;
Do not provide any value for column emp_id when you INSERT rows in table employee.
Change the table creation as below:
CREATE TABLE employee (
emp_id INT(6) UNSIGNED NOT NULL AUTO_INCREMENT,
last_name VARCHAR(25) NOT NULL,
first_name VARCHAR(40) NOT NULL,
dept_name varchar(50) NOT NULL
PRIMARY KEY(emp_id),
FOREIGN KEY(dept_name) REFERENCES department_tbl(dept_name)
) AUTO_INCREMENT=200;
If the table has an AUTO_INCREMENT column then it must be the PRIMARY KEY of the table. I removed dept_name from the definition of the PK above. I also removed the default value 0 from the emp_id column. It's default value is generated by MySQL using the AUTO_INCREMENT policy.
When you INSERT a new record into the employee table all you have to do is to not provide any value for the emp_id column:
INSERT INTO employee (last_name, first_name, dept_name)
VALUES ('Doe', 'John', 'accounting');
Then use the LAST_INSERT_ID() MySQL function to retrieve the value of the emp_id generated on insertion.
The language or the library you use to develop the client application probably has a function that wraps LAST_INSERT_ID() and returns its value.
I've got this situation: a set of hotel that has to deal with bookings. Each client can choose a room of the given hotel, from a date START_DATE to a date END_DATE. I want to check in the table BOOKING if it's possible to book from the date START_DATE to END_DATE because there's no other booking in that period.
Here's the code:
CREATE TABLE HOTEL(
Name varchar(30) PRIMARY KEY,
City varchar(30)
);
CREATE TABLE ROOM(
HotelName varchar(30) REFERENCES HOTEL (Name),
RoomNumber int(11),
PRIMARY KEY(HotelName , RoomNumber )
);
CREATE TABLE CLIENT(
ClientCode char(16) PRIMARY KEY
);
CREATE TABLE BOOKING(
HotelName varchar(30)
RoomNumber int(11),
ClientCode char(16) REFERENCES CLIENT(ClientCode ),
StartDate date,
EndDate date,
PRIMARY KEY(HotelName , NumeroStanza, CodiceCliente, StartDate, EndDate),
FOREIGN KEY (HotelName , RoomNumber ) REFERENCES ROOM(HotelName , RoomNumber ),
CHECK (????)
);
How can I say: CHECK if given START_DATE < END_DATE, then START_DATE not between A and B, then END_DATE not between A and B, for every interval of date A and B already in the table?
The dialet is MySql
Many thanks