I'm trying to create a procedure that adds data into two tables at the same time but using mySQL, but I don't have much experience using if/else statement in database so could someone tell me how I can fix my code
Here the Attributes:
Customer information: ID,Name, Address, Telephone.
Staff information: ID, Name, Phone
Camera/Len Type: ID,Name
Camera: ID, typeID, Model, Status, Color, Hiring Price (per day), Paying Price (in case of loss).
Len: ID, TypeID, Model, Status, Hiring Price (per day), Paying Price (in case of loss).
Order orderID, customerID, employeeID, hireDate, returnDate
OrderDetail: orderID, cameraID, lenID, cameraQuantity, lenQuantity, Status(paid/not paid), pStatus(Lost/Ok)
Here's the Procedure code:
DELIMITER $$
Create Procedure addOrder(IN cust_id int, IN camera_id int, IN len_id int,
IN emp_id int, IN c_quantity int,IN l_quantity int,
IN status char(30), IN p_Status char(30), IN hire_date date, IN return_date
date)
begin
Declare order_id int;
Declare hireTime int;
Declare totalC int;
Declare totalL int;
Declare totalP int;
Select order_id = max(orderID) from orders;
if orderID is null then set order_id = 1;
Set hireTime = DATEDILL(hire_date, return_date);
if hire_date == return_date then set hireTime = 1;
if p_Status = "Lost" then set
select totalC = hireTime*c_quantity*hPrice + pPrice from Camera as C
inner join orderDetail as OD on C.camID = OD.camera_id inner join Orders
as O on O.orderID = OD.order_id;
select totalL = hireTime*l_quantity*hPrice + pPrice from Lens as L
inner join orderDetail as OD on L.lenID = OD.len_id inner join Orders as
O on O.orderID = OD.order_id;
Set totalP = totalL + totalC;
else set
select totalC = hireTime*c_quantity*hPrice + pPrice from Camera as C
inner join orderDetail as OD on C.camID = OD.camera_id inner join Orders
as O on O.orderID = OD.order_id;
select totalL = hireTime*l_quantity*hPrice + pPrice from Lens as L
inner join orderDetail as OD on L.lenID = OD.len_id inner join Orders as
O on O.orderID = OD.order_id;
Set totalP = totalL + totalC;
end if;
insert into Orders(custID, empID, hireDate, returnDate)
values (cust_id, emp_id,hire_date, return_date);
insert into orderDetail(orderID, cameraID, lenID, totalPrice, camQuantity,
lenQuantity, status, pStatus) values (order_id,camera_id, len_id, totalP,
c_quantity, l_quantity, status, p_Status);
end $$
DELIMITER
I think u need to use view table to add all tables after that use stored procedure. And I give you and example I think u can figure out.
CREATE PROCEDURE [dbo].[sp_CMIDByID] #UID INT, #TID INT
AS
BEGIN
DECLARE #CMID INT
IF(#TID IS NULL AND #UID IS NOT NULL)
BEGIN
SELECT #TID = TID, #CMID = CMID FROM tbl_U WHERE UID = #UID
END
IF (#CMID IS NULL AND #TID IS NOT NULL)
BEGIN
SELECT #CMID = CMID FROM tbl_T WHERE TID = #TID
END
SELECT #CMID
END
Related
I've create store procedure with parameters in mariaDB. When I call the store procedure its return empty row although every single tables contains many data. This is the result when I make a call:
call sp_rpt_trans('2020','10');
/* Affected rows: 0 Found rows: 0 Warnings: 0 Duration for 1 query: 0.141 sec. */
Below is my code:
DELIMITER //
CREATE PROCEDURE sp_rpt_trans (_year VARCHAR(10),_month VARCHAR(10))
BEGIN
create TEMPORARY table if not exists rpt_trans1 (
category varchar(100) NULL,
pos VARCHAR(40) NULL,
id VARCHAR(40) NULL,
description VARCHAR(100) NULL,
created_on datetime NULL,
handling_fee_amt DECIMAL(22,6) NULL,
amt DECIMAL(22,6) NULL,
outlet_commission DECIMAL(22,6) NULL,
weight DECIMAL(10,2) NULL
);
insert into rpt_trans1 (
category, pos, id, description, created_on, handling_fee_amt, amt, outlet_commission, weight)
SELECT
*
FROM
(
SELECT
'courier' AS category,
pt.id pos,
o.id,
o.description,
pt.created_on,
ct.handling_fee_amt,
ct.cour_amt AS amt,
ct.outlet_commission,
ct.weight
from
pos_trans pt
inner join mgt_outlet o on o.id = pt.mgt_outlet_id
and date_format(pt.created_on, '%Y') = _year
AND date_format(pt.created_on, '%m') = _month
inner join pos_trans_dt ptd on pt.id = ptd.pos_trans_id
inner join cour_trans ct on ct.id = ptd.cour_trans_id
AND ct.mgt_outlet_id = o.id
UNION ALL
SELECT
'bill' AS category,
pt.id pos,
o.id,
o.description,
pt.created_on,
bt.handling_fee_amt,
bt.amount AS amt,
bt.outlet_commission,
0 as weight
from
pos_trans pt
inner join mgt_outlet o on o.id = pt.mgt_outlet_id
and date_format(pt.created_on, '%Y') = _year
AND date_format(pt.created_on, '%m') = _month
inner join pos_trans_dt ptd on pt.id = ptd.pos_trans_id
inner join bill_trans bt on bt.id = ptd.bill_trans_id
UNION ALL
SELECT
'insurance' AS category,
pt.id pos,
o.id,
o.description,
pt.created_on,
0 AS handling_fee_amt,
ins.amount AS amt,
ins.outlet_commision,
0 as weight
from
pos_trans pt
inner join mgt_outlet o on o.id = pt.mgt_outlet_id
and date_format(pt.created_on, '%Y') = _year
AND date_format(pt.created_on, '%m') = _month
inner join pos_trans_dt ptd on pt.id = ptd.pos_trans_id
inner join ins_trans ins on ins.id = ptd.ins_trans_id
) com1
where
date_format(created_on, '%Y') = _year
AND date_format(created_on, '%m') = _month
ORDER BY
created_on ;
TRUNCATE TABLE rpt_trans1 ;
DROP TEMPORARY TABLE if exists rpt_trans1 ;
END //
DELIMITER ;
What is the cause?
Please advice. Thanks.
I try to create a function, that returns the summary on the n-th row, where n defined by the order a query result.
This is what I have:
CREATE DEFINER=`root`#`localhost` FUNCTION `fn_inventory_stock_on_note`( fIngredient int, fInventory int, fNote int ) RETURNS float
DETERMINISTIC
BEGIN
DECLARE tStock float;
DECLARE tNoteRow int;
DECLARE tDummy int;
DECLARE rStock float;
DECLARE rRow int;
SET tNoteRow = 0;
SET #rRow := 0;
SELECT #rRow := #rRow + 1, b.ID
INTO tNoteRow, tDummy
FROM fn_inventory_book b
LEFT JOIN fn_inventory_book_in bi ON b.id = bi.bookid
LEFT JOIN fn_inventory_book_out bo ON b.id = bo.bookid
LEFT JOIN fn_dict_transactions t ON b.transactionid = t.id
WHERE b.inventoryid = fInventory
AND ( bi.ingredientid = fIngredient OR bo.ingredientid = fIngredient )
HAVING b.ID = fNote
ORDER BY b.date ASC, t.direction ASC;
SET #rRow := 0;
SET #rStock := 0;
SELECT rStock INTO tStock
FROM ( SELECT #rRow := #rRow + 1 as rRow, #rStock := #rStock + ifnull( if( bi.id is not null, bi.quantity, bo.quantity ), 0 ) * t.direction as rStock
FROM fn_inventory_book b
LEFT JOIN fn_inventory_book_in bi ON b.id = bi.bookid
LEFT JOIN fn_inventory_book_out bo ON b.id = bo.bookid
LEFT JOIN fn_dict_transactions t ON b.transactionid = t.id
WHERE b.inventoryid = fInventory
AND ( bi.ingredientid = fIngredient OR bo.ingredientid = fIngredient )
ORDER BY b.date ASC, t.direction ASC ) as q
WHERE rRow = tNoteRow;
RETURN tStock;
END
Where fIngredient and fInventory is an id for the query's filter, and fNote is a PK from the fn_inventory_book table.
The first select gets the required row's number in the order, which works fine.
My problem is in the second query, which in the subquery creates a table with the same filter and order like the first select, with the same row numbers, and the cumulative quantity of each row. And in the main query I filter that with the row number I got in the first select.
At least this is what should happen. But instead of that, when I run the function like:
select fn_inventory_stock_on_note( 1545, 18, 124167 ) as stock from dual;
It returns NULL, but if I run the second query separately with the same params, I get an amount back.
But not the right number because if I only run the second query's subquery, the row numbers aren't in order (1,2,3,6,7,4,5,8,9,10 instead of 1,2,3,..,10).
What am I doing wrong? Any help will be appreciated.
Feel free to ask if my description isn't clear.
I figured out a solution for my problem, but if anyone has a better one, please share it, because I don't think mine is the right one, although it does the job.
DROP function IF EXISTS `fn_inventory_stock_on_note`;
DELIMITER $$
CREATE DEFINER=`root`#`localhost` FUNCTION `fn_inventory_stock_on_note`( fIngredient int, fInventory int, fNote int, fItem int ) RETURNS float
DETERMINISTIC
BEGIN
DECLARE tStock float;
DECLARE tNoteRow int;
DECLARE rStock float;
DECLARE rRow int;
SET #rRow := 0;
DROP TEMPORARY TABLE IF EXISTS stock_temp;
CREATE TEMPORARY TABLE stock_temp ( num int, BookID int, ItemID int, qty float );
INSERT INTO stock_temp ( SELECT #rRow := #rRow + 1 as num, q.*
FROM ( SELECT b.id as BookID, if( bi.id is not null, bi.id, bo.id ) as ItemID,
ifnull( if( bi.id is not null, bi.quantity, bo.quantity ), 0 ) * t.direction as qty
FROM fn_inventory_book b
LEFT JOIN fn_inventory_book_in bi ON b.id = bi.bookid
LEFT JOIN fn_inventory_book_out bo ON b.id = bo.bookid
LEFT JOIN fn_dict_transactions t ON b.transactionid = t.id
WHERE b.inventoryid = fInventory
AND ( bi.ingredientid = fIngredient OR bo.ingredientid = fIngredient )
ORDER BY b.date ASC, t.direction ASC ) as q );
SELECT num INTO tNoteRow
FROM stock_temp st
WHERE st.BookID = fNote
AND st.ItemID = fItem;
SELECT sum( st.qty ) INTO tStock
FROM stock_temp st
WHERE st.num <= tNoteRow;
RETURN tStock;
END$$
DELIMITER ;
I have these queries and I want to insert these results in to a single temporary table. How Can I do that?
select date(max(created_date)) AS 'Last Shipped Date',
sum(item_count) AS 'Last Shipped Units'
from order
where is_shipped = 1
AND date(shipped_date) = (select date(max(shipped_date)) from order);
select
count(distinct o.key) AS 'ACTIVE ',
count(od.ean) AS 'Active_ Units'
from order o
left join order_details od on o.id = od. order_details
Where o.is_active = 1;
select count(distinct order_key) AS 'Total_Orders_Shipped_Yesterday',
sum(item_count) AS 'Total_units_Shipped_yesterday'
from order
where datediff(curdate(), modified_date)=1
AND is_shipped =1;
select count(distinct liquidation_order_id) AS 'orders cancelled',
count(ean) AS 'Units cancelled'
from order_details
where datediff(curdate(), modified_date)=1
AND order_details_status_ =4;
There may be a way to do it in one query, but it will be complicated. It's easier to just do a series of UPDATE queries that fill in the appropriate columns in the table by joining with the other queries that calculate the values.
CREATE TEMPORARY TABLE tempTable (
`Last Shipped Date` DATE,
`Last Shipped Units` INT,
Active INT,
Active_Units INT,
Total_Orders_Shipped_Yesterday INT,
Total_units_Shipped_yesterday INT,
`orders cancelled` INT,
`Units cancelled` INT);
INSERT INTO tempTable (`Last Shipped Date`, `Last Shipped Units`)
select date(max(created_date)) AS 'Last Shipped Date',
sum(item_count) AS 'Last Shipped Units'
from order
where is_shipped = 1
AND date(shipped_date) = (select date(max(shipped_date)) from order);
UPDATE tempTable AS t
JOIN order o
left join order_details od on o.id = od. order_details
SET t.Active = count(distinct o.key), t.Active_Units = count(od.ean)
Where o.is_active = 1;
UPDATE tempTable AS t
JOIN order
SET t.Total_Orders_Shipped_Yesterday = count(distinct order_key),
t.Total_units_Shipped_yesterday = SUM(item_count)
where datediff(curdate(), modified_date)=1
AND is_shipped =1;
UPDATE tempTable AS t
JOIN order_details
SET t.`orders cancelled` = count(distinct liquidation_order_id),
t.`Units cancelled` = COUNT(ean)
where datediff(curdate(), modified_date)=1
AND order_details_status_ =4;
I am trying to call one stored procedure withing another - using an if statement.
I am getting an error so I believe that I have something out of sequence
CREATE PROCEDURE reportFreeCoolingTrackerCalls (
IN fromDate varchar (50),
IN toDate varchar (50),
IN timeZone varchar (50))
BEGIN
DECLARE startDate varchar (50);
DECLARE endDate varchar (50);
DECLARE mylogID Int;
SET startDate = FROM_UNIXTIME(fromDate/1000);
SET endDate = FROM_UNIXTIME(toDate/1000);
IF (l1.activityId = t2.activityId)
THEN CALL reportFreeCoolingTrackerError (
fromDate,
toDate,
timeZone );
ELSEIF (l1.activityId != t2.activityId)
THEN CALL reportFreeCoolingTracker (
fromDate,
toDate,
timeZone );
END IF;
SELECT l1.activityId,t2.activityId
FROM logs l
INNER JOIN groups g ON g.groupId = l.groupId
LEFT JOIN groups g1 ON g.parentId = g1.groupId
LEFT JOIN groups g2 ON g1.parentId = g2.groupId
LEFT JOIN groups g3 ON g2.parentId = g3.groupId
INNER JOIN activities a ON l.logId = a.logId
INNER JOIN log1644 l1 ON a.activityId = l1.activityId
INNER JOIN log1644 t2 ON t2.recordId = l1.recordid + 1
INNER JOIN items i ON l.logId = i.logId AND i.name LIKE '%KW%'
INNER JOIN users u ON l1.userId = u.userId AND i.name LIKE '%KW%'
WHERE i.itemID = "31985" AND l1.activityId = 1257
AND l1.started
BETWEEN startDate
AND endDate
ORDER BY l1.recordId,l1.started;
END //
DELIMITER ;
ERROR
Unknown table 'l1' in field list
I think this code is causing the trouble for you:
IF (l1.activityId = t2.activityId) --Here l1 and t2 are not known
THEN CALL reportFreeCoolingTrackerError (
fromDate,
toDate,
timeZone );
ELSEIF (l1.activityId != t2.activityId) --Here l1 and t2 are not known
THEN CALL reportFreeCoolingTracker (
fromDate,
toDate,
timeZone );
END IF;
as in this line l1 is not known. Similarly t2 is also not known
Table aliases (such as INNER JOIN log1644 l1 ON... are only visible in the statement (in your case a SELECT) that contains them.
You'll need to refer to the full table name outside of that select.
As for the logic.... you'll need to populate the values you need in the SP call by using a select, and populating them into variables. Alternatively, use a select subquery in the call itself, but that would be a maintenance headache!
I have the following tables:
Suppliers(Sno, Sname, Address)
Parts(Pno, Pname, Colour)
Catalogue(Sno, Pno, Price)
and I want to find the Sno of the suppliers who supply every part.
So far, I've written this:
SELECT s.sname
FROM suppliers s JOIN catalogue c
USING s.sno
Now how do I write the part "suppliers that supply every part"?
I was thinking about having the count(*) from parts = count(pno) for each supplier Sno. Could someone please give me a hint/write the first part of the equality?
Thanks!
SELECT s.sname
FROM suppliers s
INNER JOIN catalogue c
ON s.Sno = c.Sno
GROUP BY s.sname
HAVING COUNT(c.Pno) = (SELECT COUNT(Pno) FROM Parts)
You're close. You need to add a group by/having clause with a subquery:
group by s.sname having count(*) = (select count(*) from catalogue)
Off the top of my head, you could write
SELECT s.Sno
FROM suppliers s
WHERE NOT EXISTS (
SELECT p.Pno
FROM parts p
WHERE NOT EXISTS (
SELECT c.*
FROM catalogue c
WHERE c.Pno = P.Pno
AND c.Sno = S.Sno
)
)
i.e. supplier where not exists (part that we don't supply), for a solution avoiding counts. No idea if this would be more or less efficient than the counts.
SELECT s.Sno, s.Sname
FROM Suppliers s
CROSS JOIN Parts p
LEFT JOIN Catalogue c ON s.Sno = c.Sno AND p.Pno = c.Pno
GROUP BY s.Sno, s.Sname
HAVING COUNT(*) = COUNT(c.Pno)
Try this:
alter proc clr
#c char(10),
#pno int output
as
begin
declare #f int
if exists(select p# from p where colour=#c)
begin
select #pno=p# from p where colour=#c
--set #f=1
end
-- else
-- set #f=0
-- return #f
end
--clr 'red',2
select p# from p where colour='red'
alter proc prcs
#c char(20)
as
begin
declare #pno numeric(2)
declare #f int
exec #f=clr #c,#pno output
--if #f=1
-- begin
select #pno
select s# from sp where p#=#pno
--set #i=1
-- end
--set #i=0
--return #i
end
prcs 'red'
select * from sp
select * from p,sp where p.p#=sp.p# and colour='red'
alter proc prcj
#c char(10)
as
begin
declare #i int
exec #i=prcs #c
if #i=1
begin
print'list of supplier'
select sname from s
where s#=#c
end
else
print'this record is not found'
end