delimiter $$
drop procedure if exists getEmptySeats $$
create procedure getEmptySeats(flight_number char(5),flight_date date)
begin
select seatingID as Seats, concat(Seats.rowNumber, Seats.seatNumber) as Seat
from Seating
where
aircraftID = aircraft_id and
seatID not in
( Select seatID from Seating
inner join Seats on Seating.seatID = Seats.seatID
inner join Booking on Seating.bookingNumber = Booking.bookingNumber
inner join Flights on Booking.flightCode = Flights.flightCode
inner join FlightSchedule on Flights.flightNumber = FlightSchedule.flightNumber
where flightNumber = flight_number and flightDate = flight_date)
order by seatingID;
end $$
ORDER BY RAND()
LIMIT 1
delimiter ;
The procedure is suppose to give a random seat in a specific airplane.
I have no idea what is wrong and I have searched the internet for so long and haven't found any thing that helped.
When I call the procedure it gives this:
Error Code: 1054. Unknown column 'Seats.rowNumber' in 'field list'
Here is the Seats table:
seatID INT(11)
rowNumber TINYINT(4)
seatNumber CHAR(1)
seatPlacement VARCHAR(15)
plainID CHAR(6)
You need to join it with Seats table. The one used as a subquery can not be accessed directly
As #Madhivanan mentioned, you need to join it with the Seats table.
There were also a few ambiguous columns which needed fixing (prefixing with the table name usually is the easiest answer unless you give the table an alias)
delimiter $$
drop procedure if exists getEmptySeats $$
create procedure getEmptySeats(flight_number char(5),flight_date date)
begin
select seatingID as Seats, concat(Seats.rowNumber, Seats.seatNumber) as Seat
from Seating
inner join Seats on Seating.seatID = Seats.seatID
where
aircraftID = aircraft_id and
seating.seatID not in
( Select seating.seatID from Seating
inner join Seats on Seating.seatID = Seats.seatID
inner join Booking on Seating.bookingNumber = Booking.bookingNumber
inner join Flights on Booking.flightCode = Flights.flightCode
inner join FlightSchedule on Flights.flightNumber = FlightSchedule.flightNumber
where Flights.flightNumber = flight_number and flightDate = flight_date)
order by seatingID;
end $$
ORDER BY RAND()
LIMIT 1
delimiter ;
Related
I am working on converting a T-SQL stored procedure into MySQL. I am not familiar with T-SQL and am working on becoming more familiar with temp tables and stored procedures. Thanks for your help in advance.
The T-SQL original looks like this (EDIT: note this is only a portion of the original procedure used to produce a report):
DROP TABLE IF EXISTS #accounts;
SELECT d.data_id
,p.pp_name AS name
,CONVERT(tinyint,1) AS flag
,d.pd_date
,CONVERT(char(6),pd_date,112) AS date_period
,CONVERT(varchar(3),0) AS n_phones
INTO #accounts
from table_detail d
JOIN table_pool p ON d.pp_id = p.pp_id
JOIN table_type t ON p.pp_type_id = t.pp_type_id
JOIN Inventory i ON d.data_id = i.data_id
JOIN Product pr ON i.product_id = pr.product_id
WHERE pp_name IN (SELECT name FROM Sandbox..desired_sandbox)
AND DATEDIFF(MONTH,pd_date,GETDATE()) < 3
UPDATE a
SET a.flag = 0
FROM #accounts a
JOIN table_detail d ON a.data_id = d.data_id
JOIN table_pool p ON d.pp_id = p.pp_id
WHERE d.pd_date < a.pd_date
AND pp_name != 'error';
My current update is below. Do I need to wrap this in a CREATE TEMPORARY TABLE IF NOT EXISTS accounts AS (<insert query here>) instead of the INTO #accounts?
SELECT d.data_id
,p.pp_name AS name
,CONVERT(tinyint,1) AS flag
,d.pd_date
,DATE_FORMAT(pd_date,'%Y%m%d') AS date_period
,CONVERT(varchar(3),0) AS n_phones
FROM table_detail d
JOIN table_pool p ON d.pp_id = p.pp_id
JOIN table_type t ON p.pp_type_id = t.pp_type_id
JOIN Inventory i ON d.data_id = i.data_id
JOIN Product pr ON i.product_id = pr.product_id
WHERE pp_name IN (SELECT name FROM Sandbox..desired_sandbox)
AND TIMESTAMPDIFF(MONTH,pd_date,NOW()) < 3
Then do something like this assuming the syntax is right:
UPDATE accounts a -- Is this the correct way to add an alias and update the temp table?
JOIN table_detail d ON a.data_id = d.data_id
JOIN table_pool p ON d.pp_id = p.pp_id
SET a.flag = 0
WHERE d.pd_date < a.pd_date
AND pp_name != 'error';
Finally, I assume I could follow this post to wrap the final query into a stored procedure, correct? To summarize the code in the post:
drop procedure if exists procedure_name;
DELIMITER $$
create procedure procedure_name ()
BEGIN
DROP TEMPORARY TABLE IF EXISTS accounts;
CREATE TEMPORARY TABLE accounts AS (
SELECT...
FROM...
WHERE...
;
)
UPDATE accounts
JOIN ...
JOIN ...
SET...
WHERE...;
DROP TEMPORARY TABLE accounts; -- otherwise it survives the stored proc call
END
$$ -- signify end of block
DELIMITER ; -- reset to default delimiter
I wanted to post the solution that finally worked for me for others that might be having the same issue. The code below resolves this.
DROP PROCEDURE IF EXISTS procedure_name;
DELIMITER $$
CREATE PROCEDURE procedure_name ()
BEGIN
DROP TEMPORARY TABLE IF EXISTS accounts;
CREATE TEMPORARY TABLE accounts AS (
SELECT d.data_id
,p.pp_name AS name
,1 AS flag
,d.pd_date
,DATE_FORMAT(pd_date,'%Y%m%d') AS date_period
,CONVERT(varchar(3),0) AS n_phones
FROM table_detail d
JOIN table_pool p ON d.pp_id = p.pp_id
JOIN table_type t ON p.pp_type_id = t.pp_type_id
JOIN Inventory i ON d.data_id = i.data_id
JOIN Product pr ON i.product_id = pr.product_id
WHERE pp_name IN (SELECT name FROM Sandbox..desired_sandbox)
AND TIMESTAMPDIFF(MONTH,pd_date,NOW()) < 3
);
-- Update the temp table based on specified criteria
UPDATE accounts
JOIN ...
JOIN ...
SET...
WHERE...;
-- Create final Query for report
SELECT ...
FROM accounts
WHERE ...
GROUP BY ... -- whatever you need for final query
DROP TEMPORARY TABLE accounts; -- otherwise it survives the stored proc call
END
$$ -- signify end of block
DELIMITER ; -- reset to default delimiter
However, it is important to note the limits of MySQL temporary tables. Although I did not indicate it in my original post, later, I was attempting to join the temporary table onto itself. I needed to follow the suggestion outlined here. Essentially, if you need to refer to a temp table with itself you need to make a copy of the temp table: CREATE TEMPORARY TABLE accounts2 AS (SELECT * FROM accounts). Then you can join a temp table to itself.
While creating procedure following error occurs:
Error Code: 1221. Incorrect usage of UNION and INTO
My Procedure is:
SET sql_mode=ORACLE;
DELIMITER $$
CREATE PROCEDURE MARK_ATTENDANCE (IN EmployeeId INTEGER)
BEGIN
DECLARE EmpShift INTEGER(10);
DECLARE EmpMarkLoc INTEGER(10);
SET EmpShift = 0;
SET EmpMarkLoc = 0;
SELECT ed.default_shift, sl.location_id INTO EmpShift,EmpMarkLoc
FROM EMPLOYEE ed
LEFT JOIN sublocation sl
ON sl.sublocation_id = ed.sub_location_id
UNION ALL
SELECT ed.default_shift, sl.location_id
FROM EMPLOYEE ed
RIGHT JOIN sublocation sl
ON sl.sublocation_id = ed.sub_location_id
WHERE sl.sublocation_id IS NULL
AND emp_id = EmployeeId;
END ;
$$
DELIMITER ;
Actually I wanted a FULL OUTER JOIN and ended up on UNION ALL and tried to store output in some variables like EmpShift and EmpMarkLoc for further usage.
SELECT #EmpShift:=ed.default_shift, #EmpMarkLoc:=sl.location_id
used above in place of
SELECT ed.default_shift, sl.location_id INTO EmpShift,EmpMarkLoc
You can put the unioned queries in a derived table and select from there into the variables
SELECT u.default_shift,
u.location_id
INTO empshift,
empmarkloc
FROM (SELECT ed.default_shift,
sl.location_id
FROM employee ed
LEFT JOIN sublocation sl
ON sl.sublocation_id = ed.sub_location_id
UNION ALL
SELECT ed.default_shift,
sl.location_id
FROM employee ed
RIGHT JOIN sublocation sl
ON sl.sublocation_id = ed.sub_location_id
WHERE sl.sublocation_id IS NULL
AND emp_id = employeeid) u;
But be aware, if the unioned querys can select more than one row an assignment to scalar variables is problematic.
I am new to triggers but have coded this one
DELIMITER $$
CREATE TRIGGER stockupdate
AFTER INSERT ON inventory.orderdetails
FOR EACH ROW
BEGIN
UPDATE inventory.stockitem s
INNER JOIN inventory.OrderDetails d ON s.ID = d.Item
INNER JOIN inventory.orders o ON ebayOrderNumber = d.OrderNumber
SET s.`Sold Date` = o.`Order Date`, s.EbayOrderNumber = o.ebayOrderNumber, s.`Sale Price` = d.Price
WHERE s.ID = d.Item;
END$$
DELIMITER ;
Currently it does not update table stockitem as expected. Is there anything glaringly obvious that I have done wrong please?
Many thanks for looking.
That's because your join returns all or most records from oderDetails and oders table and you are not supressing sql_safe_updates safety feature.
You are definitely missing table alias in o ON ??.ebayOrderNumber = d.OrderNumber. Besides, WHERE s.ID = d.Item; is redundant as your table joins already do that. Your Where condition should be more explicit and tell which stock item to update.
DELIMITER $$
CREATE TRIGGER stockupdate AFTER INSERT ON inventory.orderdetails FOR EACH ROW
BEGIN
UPDATE
(inventory.stockitem s
INNER JOIN inventory.OrderDetails d ON s.ID = d.Item)
INNER JOIN inventory.orders o ON o.ebayOrderNumber = d.OrderNumber
SET
s.`Sold Date` = o.`Order Date`, -- update the stock
s.EbayOrderNumber = o.ebayOrderNumber,
s.`Sale Price` = d.Price
WHERE
d.orederNumber = NEW.OrderNumber, -- From this order
d.Item = NEW.item; -- and this item id
END$$
DELIMITER ;
Having said that, I do not understand why would you want to update the stock table with a sold price? orderDetails already contains those for you and what if you have many quantity for a single stock? i.e 100 Dell laptops. Surely you don't have 100 records for each Dell laptop in your stock item? and updating each record with sold price? Anyway i leave that up to you..
I have 3 tables, tbl_image, tbl_vehicle_image and tbl_vehicle
tbl_vehicle_image resolves a many-many relationship between tbl_image and tbl_vehicle
tbl_vehicle has a last_modified_date
How do I create a trigger that, when I change for example tbl_image.img_lnk, uses tbl_vehicle_image to find all records in tbl_vehicle that use that image, and set their last_modified_date to NOW()?
CREATE TRIGGER `trig_after_image_update` AFTER UPDATE ON `tbl_image`
FOR EACH ROW
if old.img_lnk<>NEW.img_lnk
then
update tbl_vehicle set last_modified_date=NOW() where id in (select vehicle_id from tbl_vehicle_image where image_id=OLD.id);
end if;
I don't have all field name of your table so change those. I have used id as primary key for corresponding table.
You can do this:
DELIMITER $$;
create TRIGGER UpdateLastmodifiedDate AFTER UPDATE ON tbl_image
FOR EACH ROW
BEGIN
UPDATE tbl_vehicle v
INNER JOIN tbl_vehicle_image vi ON v.vehicleId = vi.vehicleID
INNER JOIN tbl_image i ON vi.imageid = i.id
SET v.lastmodified_date = NOW()
WHERE i.img_lnk = NEW.img_lnk;
END$$
i have the following stored procedure that returns the sent emails of the latest or last inserted campaigns
"Now my aim to only show the campaigns which have "sent: count greater than "0" how could i make changes to the following sp to do it, because now it is returning all the campaigns including "0" and greater than "0" "..
Code is...
DELIMITER $$
DROP PROCEDURE IF EXISTS `couponcrusaderdev`.`sp_tblemailcampaignLoadTop4`$$
CREATE DEFINER=`anyone`#`000.000.00.00` PROCEDURE `sp_tblemailcampaignLoadTop4`(p_UserID Int(11))
SQL SECURITY INVOKER
BEGIN
SELECT EC.*,(Select MailChimpCampaignID from tblcampaignschedule where EC.CampaignID=tblcampaignschedule.CampaignID ) as MailChimpCampaignID,(Select count(MailChimpCampaignID) from tblcampaignschedule) as msent,CT.CampaignType, (Select tblcampaignschedule.ScheduleDateTime from tblcampaignschedule
where EC.CampaignID=tblcampaignschedule.CampaignID order By ScheduleDateTime desc limit 1) as CampaignDateTime,
(Select Count(*) from tblemailsent ES
inner join tblcampaignschedule CS on CS.CampaignSceduleID= ES.CampaignSceduleID
where ES.Status= 'ProcessedMessage' and CS.CampaignID = EC.CampaignID)as Sent
FROM tblemailcampaign EC
inner join tblcampalgntype CT on CT.CampaignTypeID= EC.CampaignTypeID
inner join tblcompanies C On EC.CompanyID = C.CompanyID
WHERE (p_UserID = 0 OR C.AddUserID = p_UserID)
order by CampaignDateTime desc limit 4
;
END$$
DELIMI
You should use HAVING
HAVING COUNT(sent) >= 0;
Manual:
http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html