How to implement a double constraint in SQL Server? - sql

I am designing a database project that holds records for an alumni association. My goal was to make sure that the names in the awards table only come from those who have been nominated in the alumni table (where Award_Nominated acts as a Boolean). I have tried using two booleans, one for nomination and another for winning, but that still leaves a possibility for a logical error, i.e. one can be an award winner without getting nominated. My question is how can I make sure that the award winner names only come from the alumni name values with Award_nominated as true.
The relevant tables are declared below:
CREATE TABLE Alumni
(
Alumni_ID int NOT NULL IDENTITY(1,1),
First_Name varchar(20) UNIQUE NOT NULL,
Last_Name varchar(20) UNIQUE NOT NULL,
Graduation_Year int NOT NULL,
Course_taken varchar(255) NOT NULL,
Award_Nominated bit,
Phone_Number int NOT NULL,
Email_Address varchar(255) NOT NULL,
PRIMARY KEY (Alumni_ID, First_Name, Last_Name)
);
CREATE TABLE Awards
(
Award_year int NOT NULL,
Chapters varchar(255),
Award_Winner_First_Name varchar(20) NOT NULL,
Award_Winner_Last_Name varchar(20) NOT NULL,
FOREIGN KEY (Award_Winner_First_Name) REFERENCES Alumni(First_Name),
FOREIGN KEY (Award_Winner_Last_Name) REFERENCES Alumni(Last_Name),
Award_purpose varchar(255) NOT NULL
);

Couple points:
simplify the Alumni table's primary key to be just the Alumni_ID
Don't make first and last name unique - really bad idea ....
reference the Awards table to the Alumni table solely based on the Alumni_ID - not on first and last name ....
don't duplicate the first and last name of the alumni into the Awards table -
if need be, you can get it be a JOIN to the Alumni table
I'd go with this:
CREATE TABLE dbo.Alumni
(
Alumni_ID int NOT NULL IDENTITY(1,1)
CONSTRAINT PK_Alumni PRIMARY KEY CLUSTERED,
First_Name varchar(20) NOT NULL,
Last_Name varchar(20) NOT NULL,
Graduation_Year int NOT NULL,
Course_taken varchar(255) NOT NULL,
Award_Nominated bit,
Phone_Number int NOT NULL,
Email_Address varchar(255) NOT NULL
);
CREATE TABLE dbo.Awards
(
Award_year int NOT NULL,
Alumni_ID int NOT NULL
CONSTRAINT FK_Award_Alumni REFERENCES dbo.Alumni(Alumni_ID),
Chapters varchar(255),
Award_purpose varchar(255) NOT NULL
);

Don't duplicate the names in the Awards table. Reference the Alumni ID and join.
CREATE TABLE Alumni (
Alumni_ID int not null identity(1,1),
-- It's possible to have two alumni with the same name.
-- And also to have names longer than 20 characters.
First_Name varchar(255) not null,
Last_Name varchar(255) not null,
Graduation_Year int not null,
Course_taken varchar(255) not null,
Phone_Number int not null,
Email_Address varchar(255) not null,
-- Just the Alumni_ID is sufficient
PRIMARY KEY (Alumni_ID)
);
CREATE TABLE Awards (
Award_year int not null,
Chapters varchar(255),
-- Only reference the ID
Alumni_ID int not null,
FOREIGN key (Alumni_ID) REFERENCES Alumni(Alumni_ID),
Award_purpose varchar(255) not null
);
Then join with Alumni to get their names.
select First_Name, Last_Name, Awards.*
from Awards
join Alumni on Awards.Alumni_ID = Alumni.Alumni_ID

Related

"Incorrect syntax near 'DESCRIBE'. [41,1]" No other context, can't find syntax error

New to SQL, can't figure out what is wrong in my given code. all it says is:
Incorrect syntax near 'DESCRIBE'. [41,1]
I have tried taking off the semi-colons. I really just don't know what it wants from me.
Here is my code. Anything helps, thank you!
-- Write the query to create the 4 tables below.
CREATE TABLE client (
id INT NOT NULL IDENTITY(1,1),
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
dob DATE NOT NULL,
PRIMARY KEY (id),
CONSTRAINT (full_name) UNIQUE (first_name, last_name)
);
CREATE TABLE employee (
id INT NOT NULL IDENTITY(1,1),
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
dob DATE NOT NULL,
date_joined DATE NOT NULL,
CONSTRAINT (full_name) UNIQUE (first_name, last_name),
PRIMARY KEY (id)
);
CREATE TABLE project (
id INT NOT NULL IDENTITY(1,1),
cid INT NOT NULL,
name VARCHAR(255) NOT NULL,
notes TEXT,
UNIQUE (name),
FOREIGN KEY (cid) REFERENCES client(id)
);
CREATE TABLE works_on (
eid INT NOT NULL,
pid INT NOT NULL,
start_date DATE NOT NULL,
PRIMARY KEY (eid, pid),
FOREIGN KEY (eid) REFERENCES employee(id),
FOREIGN KEY (pid) REFERENCES project(id)
);
-- Leave the queries below untouched. These are to test your submission correctly.
-- Test that the tables were created
DESCRIBE client;
DESCRIBE employee;
DESCRIBE project;
DESCRIBE works_on;
-- Test that the correct foreign keys were created
SELECT TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_SCHEMA = 'grade';
For MariaDB (and MySQL) the correct syntax for IDENTITY(1,1), is AUTO_INCREMENT, and CONSTRAINT names are not enclosed in (). Any column that is defined as AUTO_INCREMENT must also be declared as a PRIMARY KEY (this is only an issue with the project table). So your CREATE TABLE commands should look like this:
CREATE TABLE client (
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
dob DATE NOT NULL,
PRIMARY KEY (id),
CONSTRAINT full_name UNIQUE (first_name, last_name)
);
CREATE TABLE employee (
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
dob DATE NOT NULL,
date_joined DATE NOT NULL,
CONSTRAINT full_name UNIQUE (first_name, last_name),
PRIMARY KEY (id)
);
CREATE TABLE project (
id INT NOT NULL AUTO_INCREMENT,
cid INT NOT NULL,
name VARCHAR(255) NOT NULL,
notes TEXT,
PRIMARY KEY (id),
UNIQUE (name),
FOREIGN KEY (cid) REFERENCES client(id)
);
CREATE TABLE works_on (
eid INT NOT NULL,
pid INT NOT NULL,
start_date DATE NOT NULL,
PRIMARY KEY (eid, pid),
FOREIGN KEY (eid) REFERENCES employee(id),
FOREIGN KEY (pid) REFERENCES project(id)
);
Demo on dbfiddle

New to SQL, Need to check schoolwork on Fiddle - Is my code correct?

CREATE TABLE Customer_Master (
customer_ID INTEGER(30) NOT NULL AUTO_INCREMENT,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
street_address VARCHAR(100) NOT NULL,
apt INTEGER(9),
city VARCHAR(30) NOT NULL,
state VARCHAR(3) NOT NULL,
zip VARCHAR(10) NOT NULL,
home_phone INTEGER NOT NULL,
mobile_phone INTEGER(10) NOT NULL,
other_phone INTEGER(10) NOT NULL,
PRIMARY KEY (customer_ID)
);
CREATE TABLE Order_Master (
Donut_order_ID INTEGER(10) NOT NULL,
Order_date DATETIME NOT NULL,
Special_notes VARCHAR(255) NOT NULL,
Customer_ID INTEGER(30) NOT NULL,
PRIMARY KEY (Donut_order_ID),
FOREIGN KEY (Customer_ID) REFERENCES Customer_Master(Customer_ID)
);
CREATE TABLE Donut_Master (
Donut_ID VARCHAR(10) NOT NULL,
Name VARCHAR(30) NOT NULL,
Unit_price NUMERIC(10,2) NOT NULL,
PRIMARY KEY (Donut_ID)
);
CREATE TABLE Order_Details (
Donut_Order_ID INTEGER(10) NOT NULL,
Donut_ID VARCHAR(10) NOT NULL,
Quantity INTEGER(100) NOT NULL,
FOREIGN KEY (Donut_Order_ID) REFERENCES Order_Master (Donut_Order_ID),
FOREIGN KEY (Donut_ID) REFERENCES Donut_Master (Donut_ID)
);
CREATE VIEW Customer_Information AS
SELECT CONCAT (first_name,'',last_name) AS Customer_Name,
customer_ID, street_address, apt, city, state, zip, home_phone, mobile_phone, other_phone
FROM Customer_Master;
CREATE INDEX Donut
ON Donut_Master (Donut_ID);
INSERT INTO Customer_Master
VALUES
('1','Bruce','Wayne','123_Gotham','12','Gotham_City',
'NY','12345','123456789','000000000','000000000');
INSERT INTO Order_Master
VALUES ('1','2017-05-11','Please_include_plates_and_napkins','1');
INSERT INTO Donut_Master
VALUES
('1','Plain','1.50'),
('2','Glazed','1.75'),
('3','Cinnamon','1.75'),
('4','Chocolate','1.75'),
('5','Sprinkle','1.75'),
('6','Gluten-Free','2.00');
INSERT INTO Order_Details
VALUES ('1','1','1');
Well, the errors that you get should be clear enough to fix any mistakes.
There are some typos, like an extra comma in the CREATE statement of table Donut_Master and the Customer_ID of Order_Details is varchar and in Customer_Master is int. I think your INSERT statement is incomplete too, see here: https://www.w3schools.com/sql/sql_insert.asp
These are some great lessons actually that you can go through! Best of luck!

postgresql syntax error when creating a table

Hey everyone I need some help with creating tables. I have the script below and it creates a few tables. When i try to run the script it give me this error:
psql:script.sql:10: ERROR: syntax error at or near "Group"
LINE 6: CREATE TABLE Group(
Can anyone tell me what is going on?
CREATE TABLE Group(
name varchar(40) PRIMARY KEY NOT NULL
);
CREATE TABLE Artist(
name varchar(30) PRIMARY KEY NOT NULL,
birthplace varchar(20) NOT NULL,
age int NOT NULL CHECK (age > 0),
style varchar(20) NOT NULL
);
CREATE TABLE Artwork(
title varchar(40) PRIMARY KEY NOT NULL,
artist varchar(30) NOT NULL references Artist(name),
group_name varchar(40) NOT NULL references Group(name),
year int NOT NULL CHECK (year > 0),
type varchar(30) NOT NULL,
price money NOT NULL,
);
CREATE TABLE Customer(
cust_id int PRIMARY KEY NOT NULL,
name varchar(40) NOT NULL,
address varcahr(60) NOT NULL,
amount money NOT NULL CHECK(amount > 0),
like_artist varchar(30) NOT NULL references Artist(name),
like_group varchar(40) NOT NULL references Group(name)
);
it had a lot of problems
this worked for me. In postgres, names that are not all lowercase need to be double quoted. also some of your table names are reserved words, money can't be > and int, and there was a comma out of place.
CREATE TABLE "group"( name varchar(40) PRIMARY KEY NOT NULL );
CREATE TABLE artist( name varchar(30) PRIMARY KEY NOT NULL, birthplace varchar(20) NOT NULL, age int NOT NULL CHECK (age > 0), style varchar(20) NOT NULL );
CREATE TABLE artwork( title varchar(40) PRIMARY KEY NOT NULL, artist varchar(30) NOT NULL references artist(name),
group_name varchar(40) NOT NULL references "group"(name), year int NOT NULL CHECK (year > 0), type varchar(30) NOT NULL, price money NOT NULL );
CREATE TABLE customer( cust_id int PRIMARY KEY NOT NULL, name varchar(40) NOT NULL, address varchar(60) NOT NULL,
amount money NOT NULL CHECK(amount > cast(0.0 as money)), like_artist varchar(30) NOT NULL references artist(name), like_group varchar(40) NOT NULL references "group"(name) );

i used the program SQL Fiddle and it keeps telling me that the table doesn't exist,what can i do to fix the two tables referencing each other?

the Staff table references the branch table
CREATE TABLE Staff(
StaffNo VARCHAR(5) NOT NULL,
firstName VARCHAR(15) NOT NULL UNIQUE,
lastName VARCHAR(15) NOT NULL,
position VARCHAR(10) NOT NULL,
salary INTEGER
DEFAULT 3000,
CHECK (salary BETWEEN 3000 AND 25000),
email VARCHAR(25),
branchNo CHAR(6) NOT NULL,
PRIMARY KEY (StaffNo),
FOREIGN KEY (branchNo) REFERENCES Branch (branchNo));
and at the same time the branch table references the Staff table
create table Branch(
branchNo char(6) not null primary key,
street varchar(30) not null,
city varchar(20),
postCode char(5) not null,
ManagerNo varchar(5) not null,
foreign key (ManagerNo) references Staff(StaffNo));
Since your tables reference each other in the Foreign Keys you will get an error on either table creation if the other table has not been created yet. I would suggest that you remove the creation of the FOREIGN KEYs to separate ALTER TABLE statements:
CREATE TABLE Staff(
StaffNo VARCHAR(5) NOT NULL,
firstName VARCHAR(15) NOT NULL UNIQUE,
lastName VARCHAR(15) NOT NULL,
position VARCHAR(10) NOT NULL,
salary INTEGER
DEFAULT 3000,
CHECK (salary BETWEEN 3000 AND 25000),
email VARCHAR(25),
branchNo CHAR(6) NOT NULL,
PRIMARY KEY (StaffNo)
);
create table Branch(
branchNo char(6) not null primary key,
street varchar(30) not null,
city varchar(20),
postCode char(5) not null,
ManagerNo varchar(5) not null
);
alter table staff
add constraint fk1_branchNo foreign key (branchNo) references Branch (branchNo);
alter table branch
add constraint fk1_ManagerNo foreign key (ManagerNo) references Staff (StaffNo);
See SQL Fiddle with Demo
You can remove one reference from one table and keep the other.then you can retrieve data using the remainig reference.Is there any problem with that?

Foreign Key Used in Composite Primary Key

Is it possible to use a composite foreign key as a piece of a table's composite primary key?
For instance, let's say I have two tables:
CREATE TABLE DB.dbo.Partners
(
CONSTRAINT pk_Partners_Id
PRIMARY KEY (Name, City, State, Country, PostalCode),
Name VARCHAR(100) NOT NULL,
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150) NOT NULL,
State CHAR(2) NOT NULL,
Country CHAR(2) NOT NULL,
PostalCode VARCHAR(16) NOT NULL,
Phone VARCHAR(20),
Fax VARCHAR(20),
Email VARCHAR(256)
)
... and then in a second table, I would like to reference the foreign key in the second table's primary key:
CREATE TABLE DB.dbo.PartnerContacts
(
CONSTRAINT pk_PartnerContacts_Id
PRIMARY KEY (fk_PartnerContacts_PartnerId, FirstName, LastName, PhoneNumber, Email),
CONSTRAINT fk_PartnerContacts_PartnerId
FOREIGN KEY REFERENCES Partners(Name, City, State, Country, PostalCode),
FirstName VARCHAR(75) NOT NULL,
MiddleName VARCHAR(75),
LastName VARCHAR(75) NOT NULL,
PhoneNumber VARCHAR(20) NOT NULL,
MobileNumber VARCHAR(20),
FaxNumber VARCHAR(20),
Email VARCHAR(256) NOT NULL,
MailTo VARCHAR(100),
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150),
State CHAR(2),
Country CHAR(2),
PostalCode VARCHAR(16)
)
Is there any way that I can do that? Yes, it might be easier to just simply use IDENTITY columns in these tables but if I can define an actual relationship without an IDENTITY I would like to do that.
EDIT:
I wanted to provide the final, working SQL. Thanks to everyone who answered!
CREATE TABLE DB.dbo.Partners
(
CONSTRAINT pk_Partners_Id
PRIMARY KEY (Name, City, State, Country, PostalCode),
Id INT NOT NULL UNIQUE IDENTITY(1, 1),
Name VARCHAR(100) NOT NULL,
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150) NOT NULL,
State CHAR(2) NOT NULL,
Country CHAR(2) NOT NULL,
PostalCode VARCHAR(16) NOT NULL,
Phone VARCHAR(20),
Fax VARCHAR(20),
Email VARCHAR(256)
)
CREATE TABLE DB.dbo.PartnerContacts
(
CONSTRAINT pk_PartnerContacts_Id
PRIMARY KEY
(PartnerId, FirstName, LastName, PhoneNumber, Email),
PartnerId INT NOT NULL CONSTRAINT fk_PartnerContacts_PartnerId FOREIGN KEY REFERENCES Partners(Id),
FirstName VARCHAR(75) NOT NULL,
MiddleName VARCHAR(75),
LastName VARCHAR(75) NOT NULL,
PhoneNumber VARCHAR(20) NOT NULL,
MobileNumber VARCHAR(20),
FaxNumber VARCHAR(20),
Email VARCHAR(256) NOT NULL,
MailTo VARCHAR(100),
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150),
State CHAR(2),
Country CHAR(2),
PostalCode VARCHAR(16)
)
You probably need to specify the columns that are supposed to match.
CONSTRAINT fk_PartnerContacts_PartnerId
FOREIGN KEY (columns that correspond to referenced columns)
REFERENCES Partners (Name, City, State, Country, PostalCode),
So you need to provide the five column names whose values are supposed to match the values of {Name, City, State, Country, PostalCode} in the table "Partners". i'm pretty sure youcan't do that with your current structure. You won't be able to match "Name". I think you're looking for something along these lines.
CREATE TABLE DB.dbo.PartnerContacts (
-- Start with columns that identify "Partner".
partner_name VARCHAR(100) NOT NULL,
partner_city VARCHAR(150) NOT NULL,
partner_state CHAR(2) NOT NULL,
partner_country CHAR(2) NOT NULL,
partner_postcode VARCHAR(16) NOT NULL,
CONSTRAINT fk_PartnerContacts_PartnerId
FOREIGN KEY (partner_name, partner_city, partner_state, partner_country, partner_postcode)
REFERENCES Partners (Name, City, State, Country, PostalCode),
FirstName VARCHAR(75) NOT NULL,
MiddleName VARCHAR(75),
LastName VARCHAR(75) NOT NULL,
PhoneNumber VARCHAR(20) NOT NULL,
MobileNumber VARCHAR(20),
FaxNumber VARCHAR(20),
Email VARCHAR(256) NOT NULL,
MailTo VARCHAR(100),
Address1 VARCHAR(100),
Address2 VARCHAR(100),
Address3 VARCHAR(100),
City VARCHAR(150),
State CHAR(2),
Country CHAR(2),
PostalCode VARCHAR(16),
CONSTRAINT pk_PartnerContacts_Id
PRIMARY KEY (partner_name, partner_city, partner_state, partner_country, partner_postcode,
FirstName, LastName, PhoneNumber, Email)
);
Yes it is possible and is generally considered best DB design practice, but practically, an ID column is just easier to deal with. Think of join tables, their primary key is a composite of two foreign keys. There is no difference to using multiple foreign keys as part of a composite primary key.
Yes, that is definitely possible. We do have instances where we have a composite foreign key that is a part of the composite primary key of other table.
Let's simplify the use case little bit for the below example.
Say we have a table test1 having a composite primary key (A, B)
Now we can have a table say test2 having primary key (P, Q, R) where in (P,Q) of test2 references (A,B) of test1.
I ran the following script in the MySql database and it works just fine.
CREATE TABLE `test1` (
`A` INT NOT NULL,
`B` VARCHAR(2) NOT NULL,
`C` DATETIME NULL,
`D` VARCHAR(45) NULL,
PRIMARY KEY (`A`, `B`));
CREATE TABLE `test2` (
`P` INT NOT NULL,
`Q` VARCHAR(2) NOT NULL,
`R` INT NOT NULL,
`S` DATETIME NULL,
`T` VARCHAR(8) NULL,
PRIMARY KEY (`P`, `Q`, `R`),
INDEX `PQ_idx` (`P`,`Q` ASC),
CONSTRAINT `PQ`
FOREIGN KEY (`P`, `Q`)
REFERENCES `test1` (`A`,`B`)
ON DELETE CASCADE
ON UPDATE CASCADE);
In the above mentioned case, the database is expecting the combination of (A,B) to be unique and it is, being a primary key in test1 table.
But if you try to do something like following, the script would fail. The database would not let you create the test2 table.
CREATE TABLE `test2` (
`P` INT NOT NULL,
`Q` VARCHAR(2) NULL,
`R` DATETIME NULL,
`S` VARCHAR(8) NULL,
`T` VARCHAR(45) NULL,
INDEX `P_idx` (`P` ASC),
INDEX `Q_idx` (`Q` ASC),
CONSTRAINT `P`
FOREIGN KEY (`P`)
REFERENCES `test1` (`A`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `Q`
FOREIGN KEY (`Q`)
REFERENCES `test1` (`B`)
ON DELETE CASCADE
ON UPDATE CASCADE);
In the above mentioned case database would expect the column A to be unique individually and the same follows for column B. It does not matter if combination of (A,B) is unique.