Related
The actual problem statement looks like :
• Product(prod_id, prod_name, qty_on_hand)
• Order(cust_id, prod_id, order_date, qty_ordered)
• Customer(cust_id, cust_name, phone, address)
"Write a stored procedure to take the cust_id, prod_id and qty_ordered as
input. Procedure should check if the order for a particular customer can be
fulfilled and if yes then insert the new order and update the product
quantity on hand. Display appropriate message if the order cannot be
fulfilled.
Output parameter must have updated value of the qty_on_hand"
I am new to plsql so ignore silly mistakes. I tried to code something like this :
delimiter $$
-- creating procedure
CREATE PROCEDURE order_request( cust_id int, prod_id int, qty_ordered int)
BEGIN
IF( customer.cust_id != cust_id AND product.prod_id != prod_id AND qty_ordered > product.qty_on_hand) THEN
SELECT 'invalid details' ;
ELSE INSERT INTO `orders` (`cust_id`, `prod_id`, `order_date`, `qty_ordered`) VALUES (cust_id, prod_id, current_date(), qty_ordered) ;
END IF ;
END $$
CALL order_request(3,3,2)$$
which showing me error : unknown table customer in field list
I have solved the question. Here is the solution:
CREATE DATABASE shopping;
USE shopping;
CREATE TABLE product( prod_id INT PRIMARY KEY, prod_name varchar(20), qty_on_hand INT CHECK(qty_on_hand >= 0));
CREATE TABLE customer( cust_id INT PRIMARY KEY, cust_name varchar(20), phone INT, address varchar(20) );
-- product table insertion
INSERT INTO `product` (`prod_id`, `prod_name`, `qty_on_hand`) VALUES ('1', 'mug', '2');
INSERT INTO `product` (`prod_id`, `prod_name`, `qty_on_hand`) VALUES ('2', 'bowl', '15');
INSERT INTO `product` (`prod_id`, `prod_name`, `qty_on_hand`) VALUES ('3', 'plate', '7');
INSERT INTO `product` (`prod_id`, `prod_name`, `qty_on_hand`) VALUES ('4', 'fork', '40');
INSERT INTO `product` (`prod_id`, `prod_name`, `qty_on_hand`) VALUES ('5', 'spoon', '30');
-- customer table insertion
INSERT INTO `customer` (`cust_id`, `cust_name`, `phone`, `address`) VALUES ('1', 'duke', '1212121212', 'pune');
INSERT INTO `customer` (`cust_id`, `cust_name`, `phone`, `address`) VALUES ('2', 'finn', '190120138', 'waterland');
INSERT INTO `customer` (`cust_id`, `cust_name`, `phone`, `address`) VALUES ('3', 'buck', '98989898', 'delhi');
INSERT INTO `customer` (`cust_id`, `cust_name`, `phone`, `address`) VALUES ('4', 'larry', '738197232', 'jaipur');
INSERT INTO `customer` (`cust_id`, `cust_name`, `phone`, `address`) VALUES ('5', 'edna', '184194791', 'mumbai');
CREATE TABLE orders( cust_id INT, prod_id INT, order_date DATE, qty_ordered INT CHECK(qty_ordered > 0) , FOREIGN KEY (cust_id) REFERENCES customer(cust_id), FOREIGN KEY (prod_id) REFERENCES product(prod_id));
-- orders table insertion
INSERT INTO `orders` (`cust_id`, `prod_id`, `order_date`, `qty_ordered`) VALUES ('1', '2', '2022-09-15', '2');
delimiter $$
-- creating procedure
CREATE PROCEDURE order_request( cust_id_param INT, prod_id_param INT, qty_ordered_param INT)
BEGIN
IF EXISTS (SELECT cust_id,prod_id,qty_on_hand FROM customer,product WHERE cust_id = cust_id_param AND prod_id = prod_id_param AND qty_on_hand >= qty_ordered_param)
THEN INSERT INTO `orders` (`cust_id`, `prod_id`, `order_date`, `qty_ordered`) VALUES (cust_id_param, prod_id_param, current_date(), qty_ordered_param);
UPDATE `product` SET product.qty_on_hand = qty_on_hand - qty_ordered_param WHERE prod_id = prod_id_param ;
ELSE SELECT 'invalid details' ;
END IF ;
END $$
CALL order_request(1,1,2)$$ -- valid
CALL order_request(3,2,14)$$ -- valid
CALL order_request(5,4,4)$$ -- valid
CALL order_request(10,10,2)$$ -- invalid
select * from orders$$
select * from product$$
-- creating the funtion
CREATE FUNCTION order_details (cust_id_param INT, prod_id_param INT ) RETURNS INT
BEGIN
DECLARE ans int;
SELECT SUM(qty_ordered) INTO ans FROM orders WHERE cust_id = cust_id_param AND prod_id = prod_id_param;
RETURN ans;
END$$
-- calling the funtion
SELECT order_details(5,4)$$
I'm trying to create TRIGGERS in MySQL but I got a syntax error message. Here's my code for creating the tables and inserting the values:
The first table:
CREATE TABLE widgetSale (
id INTEGER auto_increment,
item_id INT,
customer_id INT,
quan INT,
price INT,
reconciled INT,
primary key (id));
INSERT INTO widgetSale (item_id, customer_id, quan, price, reconciled) VALUES (1, 3, 5, 1995, 0);
INSERT INTO widgetSale (item_id, customer_id, quan, price, reconciled) VALUES (2, 2, 3, 1495, 1);
INSERT INTO widgetSale (item_id, customer_id, quan, price, reconciled) VALUES (3, 1, 1, 2995, 0);
SELECT * FROM widgetSale;
My first trigger for the first table:
delimiter //
CREATE TRIGGER updateWidgetSale BEFORE UPDATE ON widgetSale for each row
BEGIN
IF NEW.reconciled = 1 THEN
SIGNAL SQLSTATE VALUE '45000'
SET MESSAGE_TEXT = 'cannot update table "widgetSale" after it has been reconciled';
END IF;
END
//
And here are my tables to create trigger for timestamps:
DROP TABLE IF EXISTS widgetSale;
CREATE TABLE widgetCustomer(
id integer auto_increment,
name TEXT,
last_order_id INT,
stamp TEXT,
primary key(id) );
CREATE TABLE widgetSale (
id integer auto_increment,
item_id INT,
customer_id INTEGER,
quan INT,
price INT,
stamp TEXT,
primary key(id) );
CREATE TABLE widgetLog (
id integer auto_increment,
stamp TEXT,
event TEXT,
username TEXT,
tablename TEXT,
table_id INT,
primary key(id));
INSERT INTO widgetCustomer (name) VALUES ('Bob');
INSERT INTO widgetCustomer (name) VALUES ('Sally');
INSERT INTO widgetCustomer (name) VALUES ('Fred');
SELECT * FROM widgetCustomer;
delimiter //
CREATE TRIGGER stampSale before insert on widgetSale for each row
BEGIN
SET NEW.stamp = CURDATE();
update widgetCustomer set last_order_id = new.item_id where widgetCustomer.id = new.customer_id;
update widgetCustomer set stamp = new.stamp;
INSERT INTO widgetLog (stamp, event, username, tablename, table_id) VALUES (NEW.stamp, 'INSERT ', 'TRIGGER', 'widgetSale', NEW.customer_id);
END
//
INSERT INTO widgetSale (item_id, customer_id, quan, price) VALUES (1, 3, 5, 1995);
INSERT INTO widgetSale (item_id, customer_id, quan, price) VALUES (2, 2, 3, 1495);
INSERT INTO widgetSale (item_id, customer_id, quan, price) VALUES (3, 1, 1, 2995);
SELECT * FROM widgetSale;
SELECT * FROM widgetCustomer;
SELECT * FROM widgetLog;
So my problem is:
I could not create the first trigger because it seems the raise function does not exist in MySQL. I was advised to use Signal statement but I don't know what syntax should I put?
I was able to create the trigger for timestamps but I got error code 1442. I don't know what went wrong with my syntax?
*Updated: I was able to solve my problems now, for the second trigger, turns out I need to CREATE TRIGGER BEFORE INSERT, not AFTER INSERT (because otherwise I cannot update the table), and wrote two UPDATE statements to update the widgetCustomer table in which I want to update the id and the stamp column, and I have to do that by writing two separate UPDATE statements.
Summary of errors from above comment thread:
You need to use DELIMITER when defining stored routines in the MySQL client. See https://dev.mysql.com/doc/refman/8.0/en/stored-programs-defining.html
Use the SIGNAL statement to raise errors in a MySQL stored routine. See https://dev.mysql.com/doc/refman/8.0/en/signal.html
Your condition appears to be reconciled = 1, and you reference that column in the row that spawned the trigger as NEW.reconciled. You don't need to SELECT from the table to get that column.
delimiter //
CREATE TRIGGER updateWidgetSale BEFORE UPDATE ON widgetSale
BEGIN
IF NEW.reconciled = 1 THEN
SIGNAL SQLSTATE VALUE '45000'
SET MESSAGE_TEXT = 'cannot update table "widgetSale" after it has been reconciled';
END IF;
END
//
User blabla_bingo noticed you had mistakenly referenced reconciled in some INSERT statements where it didn't belong. I guess it was the result of copy & paste of some lines of code.
Re error 1442: MySQL does not allow you to INSERT/UPDATE/DELETE the same table for which the trigger was spawned. In other words, if the trigger is for an operation ON widgetSale, then you can't UPDATE widgetSale in that trigger.
But you don't need to UPDATE the table to change one column in current row for which the trigger spawned. You simply reference the columns of current row with NEW.columnName like the following to set one column to a scalar value:
SET NEW.stamp = CURDATE();
CURDATE() is an equivalent way of writing DATE(NOW()).
I want to create a trigger in Mysql.
Before Insert and before Update , to only insert the values if the ID is present in another table.
Here is my trigger (before insert) which does not work:
DELIMITER $$
CREATE TRIGGER
`before_insert_id`
BEFORE INSERT ON
`table2`
FOR EACH ROW
BEGIN
DECLARE msg VARCHAR(255);
IF NEW.id =
( SELECT id
FROM table2
WHERE NEW.id not in (select id from table1)
)
THEN
SET msg = 'id not in table1';
SIGNAL SQLSTATE '45002' SET message_text = msg ;
END IF ;
END ;
$$
DELIMITER ;
Also should we insert values in table2 inside after if statement passes?or is it just for checking only?
IF NOT EXISTS (select * from table1 where id = new.id) then set msg = 'id not in table1' signal... end if; If it exists then data gets inserted automatically.
... only insert the values if the ID is present in another table.
This sound like you just need a foreign key constraint, not a trigger.
ALTER TABLE table2 ADD FOREIGN KEY (id) REFERENCES table1(id);
That will throw an error if you try to insert a row with an id that is not present in table1.
No trigger required.
how to write multiple Insert queries in single procedure?
CREATE DEFINER=`root`#`localhost` PROCEDURE `Proc_Insert`(IN `newt` VARCHAR(500), IN `news` TEXT, IN `status` VARCHAR(500), IN `ntype` VARCHAR(500), IN `img_file` VARCHAR(1500), IN `vlink` VARCHAR(500))
INSERT INTO tbl_news(newt, news, status, ntype) VALUES (newt,news,status,ntype);
SET LID = LAST_INSERT_ID();
INSERT INTO tbl_img(pic, cid, imgfile, imgtype, imgstatus) VALUES (LID,LID,img_file,ntype,status);
INSERT INTO tbl_video(cid, vlink, vdis, vstatus) VALUES (LID,v_link,news,status);
This is the first time i am using this stored procedure.
You must enclose the statements with begin and end, and add all statements that you want:
DELIMITER $$
CREATE PROCEDURE `Proc_Insert`(IN `newt` VARCHAR(500), IN `news` TEXT, IN `status` VARCHAR(500), IN `ntype` VARCHAR(500), IN `img_file` VARCHAR(1500), IN `vlink` VARCHAR(500))
BEGIN
DECLARE LID INT;
INSERT INTO tbl_news(newt, news, status, ntype) VALUES (newt,news,status,ntype);
SET LID = LAST_INSERT_ID();
INSERT INTO tbl_img(pic, cid, imgfile, imgtype, imgstatus) VALUES (LID,LID,img_file,ntype,status);
INSERT INTO tbl_video(cid, vlink, vdis, vstatus) VALUES (LID,v_link,news,status);
END$$
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `paymentStoreProcedure`(IN `inEmail` VARCHAR(100))
BEGIN
DECLARE x, y, lastID INT DEFAULT 0;
INSERT INTO `payments`(`user_name`, `email`, `billing_address`, `ch_contact`, `city`, `ch_payment_method`, `ch_card_title`, `ch_card_number`, `ch_card_expiration`, `ch_card_cvv`, `created_at`) VALUES ('Nabeel',inEmail,'nazimabad','03211234127','Karachi','bank','Nabeel Ahmed','4242424242424242','02 / 24','123', now());
SELECT MAX(id) INTO lastID FROM `payments`;
SELECT id INTO x FROM `users` WHERE email = inEmail;
INSERT INTO `payment_products`(`payment_id`, `cart_id`, `product_name`, `price`, `quantity`, `product_id`, `created_at`) SELECT lastID, x, `product_name`, `price`, `quantity`, `product_id`, now() FROM `cart_infos` WHERE cart_id = x AND is_sold = 0;
UPDATE `cart_infos` SET is_sold =1 WHERE cart_id=x;
SELECT "Payment received";
END$$
DELIMITER ;
Note: I have used this code in my website so I copied it so you can figure it out and it's executable.
can i want to create store procedure that get arguments and run an select statment inside the insert statment?
i got 2 question:
1)how to get arguments on store procedure?
2)can i run select statment in insert statment like this?
DELIMITER $$
CREATE PROCEDURE `insertGuide` #m_name varchar(45) ,#m_last varchar(45) ,#addres varchar(45) ,#mphone int
BEGIN
INSERT INTO `guides` (`id`, `name`, `lastName`, `address`, `phone`)
VALUES (select max(id)+1 from seq,#m_name,#m_last,#addres,#mphone);
END
I don't understand the first question, but regarding the INSERT statement, this should work
INSERT INTO `guides` (`id`, `name`, `lastName`, `address`, `phone`)
select max(id)+1, #m_name, #m_last, #addres, #mphone
from seq;
try like this:
DELIMITER $$
DROP PROCEDURE IF EXISTS insertGuide;
CREATE PROCEDURE insertGuide (id int, name varchar(45) ,last varchar(45) ,addres varchar(45) ,phone int(12))
BEGIN
INSERT INTO `guides` (`id`, `name`, `lastName`, `address`, `phone`)
VALUES (id, name, last, addres, phone);
END
you can run select query in insert like:
INSERT INTO `guides` (`id`, `name`, `lastName`, `address`, `phone`)
SELECT MAX(id)+1, #m_name, #m_last, #addres, #mphone
FROM seq;