edit: version 8.0.20
I'm learning sql just now, I try to fix it but I'm not able to do it.
I have 3 table
create table order(
id_order int primary key,
order_date date
);
create delivery(
id_delivery int primary key,
delivery_date date,
cod_order int,
foreign key (cod_order) references order(id_order)
);
create purchased_product(
id_product int,
cod_order int,
return_date date,
foreign key (cod_order) references order(id_order)
primary key (id_product, cod_order)
);
This is an easier scheme but it's enough.
The return_date must be less than delivery_date + 30 days
I tried to use a check on return_date but no work, so I created a view to select the delivered products only
create view product_order_delivery(date_delivered_product) as
select date_delivery
from purchased_product P right join (select date_delivery, id_order
from order right join delivery
on order.id_order = delivery.cod_order
where date_delivery is not null) OD
on P.cod_order = OD.id_order
and I tried again with check on return_date.
Can someone help me to understand how fix it?
thanks in advance :)
Two common options for solving this are:
Write a trigger to be sure the condition is true.
Write a user-defined function and use that in a check constraint.
An alternative method might suffice in your case. Change the definition of return_date so it is days_to_return. Then you can use a check constraint:
check (days_to_return between 0 and 30)
Of course, to get the actual date, you will need to join the two tables to fetch the delivery date.
EDIT:
The insert trigger would look something like this:
delimiter $$
create trigger trig_purchased_product_return_date
before insert on purchased_product
for each row
begin
select #delivery_date = delivery_date
from delivery d
where d.cod_order = new.cod_order;
if new.return_date < #delivery_date or new.return_date > #delivery_date + interval 30 day then
signal sqlstate '45000' set message_text = 'invalid return_date'
end if
end;
delimiter ;
Related
I am trying to create a table that contains the average review for every car model in a separate table. The output should look something like:
car_model_id
avg_stars
1
3
2
5
3
1
...
...
My approach to get this table is to use a function that calculates the average for every car_id that it is given. I started with the following but it yields an error because this format returns a table not an int. Also, the getAverage() function is not implemented correctly in the create table statement.
DELIMITER $$
CREATE FUNCTION getAverage(car_id_input int) RETURNS INT
BEGIN
SELECT AVG ( `car_id` ) /* To Fix */
FROM `car_user_reviews`
WHERE car_id = car_id_input;
END$$
CREATE TABLE `car_overall_stars` (
`car_id` INT NOT NULL,
PRIMARY KEY (`car_id`),
getAverage(car_id) AS `average_stars` FROM `car_user_reviews`, /* To Fix */
FOREIGN KEY (`actor_id`) REFERENCES `actor` (`actor_id`) ON DELETE RESTRICT ON UPDATE CASCADE
);
Any clues on how I can make this work? or any other approaches to take?
Using latest version of MySQL server.
As stated by #zedfoxus in the comment
create view car_rating_avg as select car_id, avg(review) from car_user_reviews group by car_id.
I´m new to SQL so I´m sorry if I make some simple mistakes. Having said that, I wanted to create a recursive table but I´m not sure how.
I have this table:
CREATE TABLE employee(
employee_id INT NOT NULL ,
Bdate DATETIME,
address VARCHAR(80),
PRIMARY KEY(supervisor_number)
);
And I have a 1:N cardinality in which 1 supervisor can supervise N supervisees. That´s why i need a recursive table, because an employee can either be a supervisor or a supervisee.
I don´t know how to create the recursive table so if anyone knows how I would be extremely grateful!
If there´s anything that isn´t clear let me know.
Thanks!
create a table of relation , you can call it supervision;
it the new table , put 2 fields : supervisor and supervisee;
these two fields are foreign keys to the table Employee ;
for example, employee number 1 is a supervisor for the employee 2 and 3, you insert two lines in the new table :
insert into supervision (supervisor, supervisee) values (1, 2), (1, 3);
Possible realization.
The table
CREATE TABLE employee(
employee_id INT NOT NULL ,
Bdate DATETIME,
address VARCHAR(80),
PRIMARY KEY(employee_id),
supervisor_id INT,
FOREIGN KEY (supervisor_id) REFERENCES employee(employee_id)
ON DELETE SET NULL ON UPDATE CASCADE );
The triggers which checks for subordinates amount (the value of 3 is hardcoded)
CREATE TRIGGER tr_bi_check_subordinates_amount
BEFORE INSERT
ON employee
FOR EACH ROW
BEGIN
IF 3 <= ( SELECT COUNT(*)
FROM employee
WHERE supervisor_id = NEW.supervisor_id ) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'No available slots for specified supervisor';
END IF;
END
CREATE TRIGGER tr_bu_check_subordinates_amount
BEFORE UPDATE
ON employee
FOR EACH ROW
BEGIN
IF 3 <= ( SELECT COUNT(*)
FROM employee
WHERE supervisor_id = NEW.supervisor_id ) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'No available slots for specified supervisor';
END IF;
END
DEMO fiddle
I'm trying to create a trigger in MySQL in order to automatically generate an entry into a table Operations from another table Accounts.
Here my tables :
CREATE TABLE Accounts (
number INT CHECK (number >= 0),
balance REAL CHECK (balance >= 0),
PRIMARY KEY (number)
);
CREATE TABLE Operations (
date DATE,
number INT REFERENCES Accounts(number),
amount REAL,
PRIMARY KEY (date, number)
);
And below, the trigger I'm trying to make work, which generate an ERROR 1064 (42000) :
CREATE TRIGGER OperationTrig
AFTER UPDATE OF balance ON Accounts
REFERENCING OLD ROW AS ooo NEW ROW AS nnn
FOR EACH ROW
WHEN(nnn.balance <> ooo.balance)
INSERT INTO Operations
VALUES(CURDATE(), nnn.number, nnn.balance - ooo.balance);
Where am I wrong ?
I think it's that WHEN clause; I don't recognize it as valid MySQL syntax. Ditto for the REFERENCING clause. (Both are valid Oracle/PostgreSQL, however.)
Try this:
CREATE TRIGGER OperationTrig
AFTER UPDATE ON Accounts
FOR EACH ROW
BEGIN
IF (NEW.balance <> OLD.balance) THEN
INSERT INTO Operations
VALUES(CURDATE(), NEW.number, NEW.balance - OLD.balance);
END IF;
END;
Is possible prevent the insertion in a mysql table after some date and time?
for example i have 2 tables:
TABLE exams
(
...
examID int primary key auto_increment,
examDate DATE,
examTime TIME,
...
)
TABLE inscripts
(
...
examID int not null references exams(examID),
insDate DATE,
insTime TIME,
...
)
i want to prevent the insertion of new inscriptions when the exam is playing.
There are some function to prevent this or check easily if current date and current time are equal or bigger than the date and time in matches table?
You could create a trigger that validates the insert before proceeding. Pseudo-code, but something like:
DELIMITER |
CREATE TRIGGER `Stop_Insert_During_Exam`
BEFORE UPDATE ON `inscripts`
FOR EACH ROW
BEGIN
DECLARE msg VARCHAR(255);
-- Check
-- Test if an exam is going on. If so:
SET msg = "You cannot add an inscription while an exam is going on.';
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
-- /Check
END;
|
Looking at your table, you already know the examid when you try to insert an inscription. So you can just grab the exam before you insert the inscription and check if it is ongoing. If it is just dont insert it and if it is not then insert it.
hi I'm quite new to mysql and I'm trying to figure out how to use triggers.
what I'm trying to do:
I have 2 tables, max and sub_max, when I insert a new row to sub_max I want to check if the SUM of the values with the same foreign_key as the new row are less than the value in the max table. I think this sounds confusing so here are my tables:
CREATE TABLE max(
number INT ,
MaxAmount integer NOT NULL)
CREATE TABLE sub_max(
sub_number INT ,
sub_MaxAmount integer NOT NULL,
number INT,
FOREIGN KEY ( number ) REFERENCES max( number ))
and here is my code for the trigger, I know the syntax is off but this is the best I could do from looking up tutorials.
CREATE TRIGGER maxallowed
after insert on sub_max
FOR EACH ROW
BEGIN
DECLARE submax integer;
DECLARE maxmax integer;
submax = select sum(sub_MaxAmount) from sub_max where sub_number = new.sub_number;
submax = submax + new. sub_MaxAmount;
maxmax = select MaxAmount from max where number = new.number ;
if max>maxmax
rollback?
END
I wanted to know if I'm doing this remotely correctly. Thanks in advance.
Caveat - I am also learning triggers.
For the section:
if max>maxmax
rollback?
Would the syntax be something like?:
IF max > maxmax THEN
DELETE the id of the new record?
ELSE
do nothing?
END IF;