Only one active for each relationship constraint - sql

So i have this problem with my assignment.
I have two entities: Order, Gifr_cupon.
I have two tables: Orders, Gift_Cupons.
Each order can have many cupons or none. Each Cupon is bound to no or an single order. But only one cupon can be active for each order.
How to enforce this by constraint?
Heres a logical and ER view with DDL:
DLL:
CREATE TABLE gift_cupons (
cupon_id INTEGER NOT NULL,
order_order_id INTEGER,
active INTEGER NOT NULL
);
ALTER TABLE gift_cupons ADD CONSTRAINT gift_cupon_pk PRIMARY KEY ( cupon_id
);
ALTER TABLE gift_cupons ADD CHECK gift_cupon_check CHECK(active IS NULL OR ( active >= 0 AND active <=1 ) );
CREATE TABLE orders (
order_id INTEGER NOT NULL
);
ALTER TABLE orders ADD CONSTRAINT order_pk PRIMARY KEY ( order_id );
ALTER TABLE gift_cupons
ADD CONSTRAINT gift_cupon_order_fk FOREIGN KEY ( order_order_id )
REFERENCES orders ( order_id );

Kind of
Cupon - is bound to -> Order;
Order - has active -> Cupon;
Cupon (
Id PK,
orderId FK Order.Id,
Unique ( Id, orderId) -- any superset of PK is unique
);
Order (
Id PK
ActiveCuponId,
(Id, ActiveCuponId) FK Cupon( OrderId, Id)
);
See fiddle https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=596b30905d02a9e5c799b16da5fff5ab

Remove the ACTIVE column from the gift_cupons table, and replace this state by a foreign key in the orders table, as in:
CREATE TABLE gift_cupons (
cupon_id INTEGER NOT NULL,
order_order_id INTEGER,
);
ALTER TABLE gift_cupons ADD CONSTRAINT gift_cupon_pk PRIMARY KEY ( cupon_id
);
CREATE TABLE orders (
order_id INTEGER NOT NULL
active_cupon INTEGER -- nullable
);
ALTER TABLE orders ADD CONSTRAINT order_pk PRIMARY KEY ( order_id );
ALTER TABLE gift_cupons
ADD CONSTRAINT gift_cupon_order_fk FOREIGN KEY ( order_order_id )
REFERENCES orders ( order_id );
alter table orders
add constraint order_active_cupon_fk foreign key (active_cupon)
references gift_cupons (cupon_id);

Related

Can have in my case foreign key duplicated value?

can have in this case foreign key duplicated value? Or better just have an index on column?
Here is my table structure:
CREATE TABLE customers(
id INT (10) NOT NULL,
name VARCHAR (50) NOT NULL,
city VARCHAR (50) NOT NULL
);
CREATE TABLE orders(
cus_id INT (10) NOT NULL ,
order_date DATETIME NOT NULL
);
CREATE TABLE products(
id INT (5) NOT NULL,
product_name VARCHAR(50) NOT NULL,
product_price INT(10) NOT NULL
);
But in orderitems table (Where I have stored the ordered products, the customer can have multiple products ordered so the foreign key value (cus_id) can be duplicated)
CREATE TABLE ordered_items(
id INT (10) NOT NULL,
cus_id INT (10) NOT NULL,
product_id INT(5) NOT NULL
);
ALTER TABLE customers ADD CONSTRAINT customer_id PRIMARY KEY ( id ) ;
ALTER TABLE orders ADD CONSTRAINT customers_id_fr FOREIGN KEY ( cus_id ) REFERENCES customers ( id );
ALTER TABLE ordered_items ADD CONSTRAINT ordered_items_fr FOREIGN KEY ( cus_id ) REFERENCES customers ( id );
EDIT:
Sorry the ordered_items table have a unique ID column as well.
Yes! you can have multiple value of cus_id inside ordered_items. however, your intention is better served if you replace cus_id by order_id from orders, Thus your relationship would sound like,
a **customer** can have multiple *orders*,
an **order** can have multiple *order items*,
and an **order item** can only have single *product*
your sql would look like this
CREATE TABLE customers(
id INT (10) NOT NULL,
name VARCHAR (50) NOT NULL,
city VARCHAR (50) NOT NULL
);
ALTER TABLE customers ADD CONSTRAINT customer_id PRIMARY KEY ( id ) ;
CREATE TABLE orders(
id INT (5) NOT NULL,
cus_id INT (10) NOT NULL ,
order_date DATETIME NOT NULL
);
ALTER TABLE orders ADD CONSTRAINT order_id PRIMARY KEY ( id ) ;
ALTER TABLE orders ADD CONSTRAINT customers_id_fr FOREIGN KEY ( cus_id ) REFERENCES customers ( id );
CREATE TABLE products(
id INT (5) NOT NULL,
product_name VARCHAR(50) NOT NULL,
product_price DOUBLE NOT NULL
);
ALTER TABLE products ADD CONSTRAINT product_id PRIMARY KEY ( id ) ;
CREATE TABLE ordered_items(
id INT (10) NOT NULL,
order_id INT (10) NOT NULL,
product_id INT(5) NOT NULL
);
ALTER TABLE ordered_items ADD CONSTRAINT ordrItm_id PRIMARY KEY ( id ) ;
ALTER TABLE ordered_items ADD CONSTRAINT ordrItm_order_frK FOREIGN KEY ( order_id ) REFERENCES orders ( id );
ALTER TABLE ordered_items ADD CONSTRAINT ordrItm_prd_frK FOREIGN KEY ( product_id) REFERENCES products ( id );

sqlite insert into table with NULL foreign key

I have the following tables: (notice that SUPP may be NULL)
CREATE TABLE IF NOT EXISTS A
(
ID INTEGER PRIMARY KEY NOT NULL
);
CREATE TABLE IF NOT EXISTS B
(
ID INTEGER PRIMARY KEY NOT NULL
);
CREATE TABLE IF NOT EXISTS C
(
ID INTEGER PRIMARY KEY NOT NULL
);
CREATE TABLE IF NOT EXISTS D
(
SID INTEGER NOT NULL,
DID INTEGER NOT NULL,
SUPP INTEGER,
PRIMARY KEY (SID, DID),
FOREIGN KEY (SID) REFERENCES A (ID),
FOREIGN KEY (DID) REFERENCES B (ID),
FOREIGN KEY (SUPP) REFERENCES C (ID)
);
Assuming table A contains ID=2 and table B contains ID=5.
I want to perform the following insert:
INSERT OR REPLACE INTO D VALUES (2,5,NULL);
However I get the following error:
Foreign key mismatch - D referencing C (INSERT INTO "main"."D" ...
I'm assuming the issue stems from the NULL foreign key but I don't know what I did wrong or how to fix it.
You need to use valid referenced value if you are inserting into child table. The ID 2 in table A and ID 5 in table B has to be present.
CREATE TABLE IF NOT EXISTS A
(
ID INTEGER PRIMARY KEY NOT NULL
);
CREATE TABLE IF NOT EXISTS B
(
ID INTEGER PRIMARY KEY NOT NULL
);
CREATE TABLE IF NOT EXISTS C
(
ID INTEGER PRIMARY KEY NOT NULL
);
CREATE TABLE IF NOT EXISTS D
(
SID INTEGER NOT NULL,
DID INTEGER NOT NULL,
SUPP INTEGER,
PRIMARY KEY (SID, DID),
FOREIGN KEY (SID) REFERENCES A (ID),
FOREIGN KEY (DID) REFERENCES B (ID),
FOREIGN KEY (SUPP) REFERENCES C (ID)
);
INSERT INTO A VALUES (2);
INSERT INTO B VALUES (5);
INSERT INTO D VALUES (2, 5, NULL);

SQL Query Error: Invalid Column Name

I am new to SQL and I have this problem, I can't seem to search on google.
This is my school work so please be patient with my coding.
Now the problem is i am doing a select query and SQL does not seem to recognize the column I need
here is an attached picture, it just says invalid column but it is clear that the column exist
Dropbox link to the picture
here is the complete code
create database Hairsalon
use Hairsalon
create table Employee
(
Employee_ID int primary key,
Name varchar(20),
Birthday date,
Gender char(1)
);
create table Inventory
(
Inventory_ID int primary key,
Name varchar(30),
Stock int
)
create table Record
(
Transaction_Number int primary key,
Transaction_Date date,
Transaction_Time time
);
alter table Record
drop column Transaction_Date
alter table Record
drop column Transaction_Time
alter table Record
add Transaction_DT varchar(30)
alter table Record
add Transaction_Description varchar(255)
Create table Inventory_Record
(
Transaction_Number int primary key foreign key references Record(Transaction_Number),
Inventory_ID int foreign key references Inventory(Inventory_ID),
);
create table Customer_Record
(
Transaction_Number int foreign key references Record(Transaction_Number),
Customer_ID int primary key,
Service_Description varchar(255),
Pay money
);
create table Customer
(
Customer_ID int foreign key references Customer_Record(Customer_ID),
Name varchar(20),
Payable money,
Session_DT varchar(20)
);
create table Employee_Record
(
Transaction_Number int primary key foreign key references Record(Transaction_Number),
Employee_ID int foreign key references Employee(Employee_ID),
Time_In time,
Time_Out time,
Record_Date date,
Customer_Count int
);
create table Salon
(
Customer_ID int foreign key references Customer_Record(Customer_ID),
Employee_ID int foreign key references Employee(Employee_ID),
Inventory_ID int foreign key references Inventory(Inventory_ID),
Transaction_Number int foreign key references Record(Transaction_Number)
);
alter table Customer
add Session_DT varchar(20)
alter table Customer
drop column Customer_ID
alter table Customer
add Customer_ID int foreign key references Customer_Record(Customer_ID)
alter table Customer_Record
add Employee_ID int foreign key references Employee(Employee_ID)
alter table Employee
add [Type] varchar(15)
alter table Employee
drop column Birthday
alter table Employee
drop column Birthday
alter table Employee_Record
drop column Time_In
alter table Employee_Record
drop column Time_Out
alter table Employee_Record
drop column Record_Date
alter table Employee_Record
add Time_In varchar(20)
alter table Employee_Record
add Time_Out varchar(20)
alter table Employee_Record
add Record_Date varchar(20)
alter table Employee_Record
drop column Customer_Count
insert into Employee
values(1,'Test Employee','M','Cashier','bday')
insert into Employee
values(-1,'Null','N','Null','Null')
insert into Employee values(1,'test1','M','HairDresser','9/8/2014')
INSERT INTO Record values(2,'')
INSERT INTO Customer_Record values(1,1,'asd',123.00,null)
INSERT INTO Customer values(1,'test1',0,'9/8/2014 8:16 AM')
SELECT * FROM Record
select * from Customer
SELECT * FROM Customer_Record
SELECT * FROM Employee
SELECT DISTINCT Customer.Name as 'Customer Name', Employee.Name as 'Attendee'
FROM Customer, Customer_Record, Employee_Record, Employee
WHERE ( Customer_Record.Transaction_Number = Employee_Record.Transaction_Number
AND Employee_Record.Employee_ID = Employee.Employee_ID
AND Customer.Customer_ID = Customer_Record.Customer_ID
) OR ( Customer_Record.Transaction_Number = Employee_Record.Transaction_Number
AND Customer_Record.Employee_ID = -1
AND Customer.Customer_ID = Customer_Record.Customer_ID
)
insert into Employee_Record values(9,1,'10:00','10:99','date')
select * from Record
select * from Customer
select * from Employee
select * from Employee_Record
select * from Customer_Record
select count(Customer_ID) from Customer
select count(Transaction_Number) from Record
insert into Customer
values(1,'test',120,DATEFROMPARTS(32,12,31))
INSERT INTO Customer_Record values(1,1,'Long Haired Customer: ',0, null)
DELETE FROM Customer WHERE Customer_ID = 1
DELETE FROM Customer
DELETE FROM Customer_Record
DELETE FROM Record
DELETE FROM Employee
DELETE FROM Employee_Record
DELETE FROM Inventory
DELETE FROM Inventory_Record
commit
According to the DDL you have presented, it seems quite obvious that Customer_Record has no Employee_ID.
You may have mixed up Customer_Record with Employee_Record or Employee_ID with Customer_ID, but something is wrong.
EDIT I had missed that you alter the table in your script to add the missing columns. In that case, Intellisense (the auto-completion system) does not take it into account unless you manually reload it (using Ctrl + Shift + R). Your query is correct and the errors will disappear once Intellisense is up to date.

Business-Logic Relationships in SQL

Can anyone please tell me how can one estabilish 1 to 0..1 and 1 to 1..* relationships between tables in SQL (Server)?
Thank you very much.
1 to 1..*
Create a Foreign key from a parent table to the primary key of the child (lookup table).
CREATE TABLE A
(
id int NOT NULL IDENTITY(1,1) PRIMARY KEY,
Somecolumn int,
SomeOtherColumn Varchar(50),
B_id int CONSTRAINT FOREIGN KEY REFERENCES B(id),
-- ...other columns
)
CREATE TABLE B
(
id int NOT NULL IDENTITY(1,1) PRIMARY KEY,
Name Varchar(50)
)
1 to 0..1
Create a table with the primary key also defined as a Foreign key to the parent table
CREATE TABLE [Master]
(
id int NOT NULL IDENTITY(1,1) PRIMARY KEY,
Somecolumn int,
SomeOtherColumn Varchar(50),
-- ...other columns
)
CREATE TABLE [Child]
(
id int NOT NULL PRIMARY KEY,
OtherColumn Varchar(50),
)
ALTER TABLE Child
ADD CONSTRAINT FK_Master FOREIGN KEY (id) REFERENCES Master(id)
One to many
Define two tables (example A and B), with their own primary key
Define a column in Table A as having a Foreign key relationship based on the primary key of Table B
This means that Table A can have one or more records relating to a single record in Table B.
If you already have the tables in place, use the ALTER TABLE statement to create the foreign key constraint:
ALTER TABLE A ADD CONSTRAINT FOREIGN KEY fk_b ( b_id ) references b(id)
* fk_b: Name of the foreign key constraint, must be unique to the database
* b_id: Name of column in Table A you are creating the foreign key relationship on
* b: Name of table, in this case b
* id: Name of column in Table B

What query creates a trigger to generate composite primary key with two fk?

I'm trying to write a command to create a trigger that generates the composite primary key. This pk is in turn based on two fk.
I'll write example tables to be more specific.
(Table I'm working on)
CREATE TABLE DB.MESSAGE (
TEXT CLOB NOT NULL,
SUBJECT VARCHAR2(2000) NOT NULL,
MSG_TYPE NUMBER(1) NOT NULL,
MAIL_ID NUMBER(10) NOT NULL
)
;
ALTER TABLE DB.MESSAGE ADD CONSTRAINT MSG_PK PRIMARY KEY ( MSG_TYPE, MAIL_ID ) ;
ALTER TABLE DB.MESSAGE ADD
(
CONSTRAINT MESSAGE_TYPE_ID_FK
FOREIGN KEY ( MSG_TYPE )
REFERENCES DB.TYPES ( TYPE_ID )
);
ALTER TABLE DB.MESSAGE ADD
(
CONSTRAINT MESSAGE_MAIL_FK
FOREIGN KEY ( MAIL_ID )
REFERENCES DB.EML_MAIL ( MAILTO_ID )
);
(Referenced tables)
CREATE TABLE DB.TYPES (
TYPE_ID NUMBER(13) NOT NULL,
NAME VARCHAR2(10) NOT NULL
)
;
CREATE TABLE DB.MAIL (
MAIL_ID NUMBER(10) NOT NULL,
MAIL VARCHAR2(350) NOT NULL
)
;
My query so far
create or replace
TRIGGER DB.TRG_MESSAGE_ID
BEFORE INSERT ON DB.MESSAGE
FOR EACH ROW
BEGIN
IF INSERTING THEN
IF :NEW."MSG_ID" IS NULL THEN
SELECT DB.TYPES.TYPE_ID ??????
INTO :NEW."MSG_ID" FROM dual;
END IF;
END IF;
END;
EDIT: So the thinking behind this question was that there would be a separated column with a concatenations of both keys that compose the composite key.
A friend told me this is wrong, you just put both fields as pk and that's that. Is this true?