mySQL finding available book and loaning it - mysql

I have created a library system and i'm trying to set up a procedure which allows you to enter an isbn and student number and from that it checks the database to see if the book is available if it is, book it. If not then give an error message.
My tables are as follows:
book - pk_isbn, author, title
copy - pk_code, duration, fk_isbn
loan - fk_code, fk_no, pk_taken, due, return_date
student - pk_no, name, school, allowedtobook
Here is what i currently have code wise *some is just sorta pseudo code i guess as it doesn't work at all currently.
DELIMITER $$
CREATE PROCEDURE issue_loan (IN book_isbn CHAR(17), IN stu_no INT)
BEGIN
DECLARE availablebooks INT;
DECLARE allowedtobook BIT;
SET availablebooks = (SELECT DISTINCT
c.isbn
FROM
loan l
INNER JOIN
student s ON l.no = s.no
INNER JOIN
copy c ON l.code = c.code
WHERE
return_date IS NOT NULL);
IF(availablebooks = book_isbn) AND s.embargo = 0 THEN
INSERT INTO loan VALUES
(code, stu_no, CURDATE(), CURDATE()+c.duration,'');
ELSE
SIGNAL SQLSTATE '450000' SET MESSAGE_TEXT ='no Books Available';
END IF;
END$$
The part which return_date IS NOT NULL should be correct as it finds any books which haven't been returned yet. Meaning they're currently booked out.

You can't set a variable to a query result set, a variable can only hold one value. You should simply add the comparison with book_isbn and s.embargo = 0 to the query.
SET #book_available = (SELECT COUNT(*)
FROM loan l
INNER JOIN student s ON l.no = s.no
INNER JOIN copy c ON l.code = c.code
WHERE c.fk_isbn = book_isbn AND s.embargo = 0 AND l.return_date IS NULL);
IF #book_available
THEN
INSERT INTO loan (fk_code, fk_no, pk_taken, due, return_date)
VALUES (code, stu_no, CURDATE(), CURDATE()+c.duration,'');
ELSE SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT ='no Books Available';
END IF

Related

MySql calculating rows based on previous row value

CREATE PROCEDURE available_rooms(
hotelname_param VARCHAR(45),
date_param DATE)
BEGIN
IF date_param IS NULL THEN -- if the booking date is null
SIGNAL SQLSTATE '22003' -- signalling error
SET MESSAGE_TEXT = 'the booing date should not be null',
MYSQL_ERRNO = 1264;
END IF;
SELECT h.Hotel_id AS HotelID,hotelname_param AS HotelName,((h.Floor_count) * (h.Roomsperfloor)) AS TotalRooms,
g.Guest_firstname AS Guestname,b.Room_count AS RoomsBooked,
(((h.Floor_count) * (h.Roomsperfloor)) - b.Room_count) AS AvailableRooms
FROM hotel h
JOIN guests g ON h.Hotel_id = g.Hotel_id
JOIN booking b ON g.Guest_id = b.Guest_id
WHERE b.BookingDate = date_param;
END
CALL available_rooms('Grand Central Inn', '2018-01-11')
when I call the procedure its displaying output as THIS
So the available rooms of first row should be used for the next row calculation, but I am not able to get that.Can anyone help me out

sql trigger two tables not empty

CREATE TRIGGER bookAvailDelete after delete on Auction
for each row
Begin
if (Select count(OLD.isbn) from Auction a > 0)
update Book b
set available =false
where OLD.isbn = isbn
;
I have two tables, Auction and Book. Auction has isbn key that references Book isbn primary key. Many auctions can point to the same book so I want this trigger to check on every auction delete, to see if it was the last auction of that book isbn. If it is, then it sets the "available" key in Book to false.
Typically, unless there were performance reasons, you'd just calculate this on the fly (instead of storing it) with queries like:
SELECT b.*
, EXISTS(SELECT * FROM Auction a WHERE a.isbn = b.isbn) AS available
FROM Book b
or (my preferred format):
SELECT b.*, (a.isbn IS NOT NULL) AS available
FROM Book b
LEFT JOIN (SELECT DISTINCT isbn FROM Auction) AS a ON b.isbn = a.isbn
;
Assuming available is int:
drop trigger bookAvailDelete;
DELIMITER //
CREATE TRIGGER bookAvailDelete after delete on Auction
for each row begin
if NOT EXISTS(Select * from Auction where isbn = old.isbn)
then
update Book b set b.available = 0 where b.isbn = old.isbn;
end if;
end;
Please compile and test below. Use a variable for the count and put end if at the end too.
delimiter //
CREATE TRIGGER bookAvailDelete after delete on Auction
for each row
Begin
DECLARE updatecount INT;
set updatecount = ( Select count(*) from Auction a where a.isbn = OLD.isbn);
if updatecount > 0 then
update Book b
set b.available =false
where b.isbn = OLD.isbn;
end if;
End;//

SAP b1 transaction Nofitication to block sales order documents with customers who has Over Credit

Situation: A customer has 50K credit limit, and 0 Balance. The customer ordered greater than its credit limit(ex. 54,000). So a transaction notification must be triggered.
Problem: Get customer creditLimit amount; get customer order balance;
What i have tried so far:
IF #object_type='17' AND #transaction_type IN ('A','U')
BEGIN
Declare #CredLimit As nvarchar(250)
SET #CredLimit= (SELECT T0.CreditLine FROM OCRD T0
WHERE T0.CardCode=#list_of_cols_val_tab_del)
IF (
SELECT (T0.DocTotal+T1.Balance) FROM ORDR T0 INNER JOIN OCRD T1 ON T0.CardCode=T1.CardCode
WHERE DocStatus='O' AND T1.DocEntry=#list_of_cols_val_tab_del) > #CredLimit
BEGIN
Set #error = -1
SET #error_message = 'Business Partner is Over Credit Limit! Save this document as DRAFT, thank you'
END
END
The SAP b1 has its own system define notification on credit limit, but we do not want to answer its "Yes or No", we just want to inform the encoder of SO that the Sales order is now making the customer Over CL and therefore save the SO as Draft.
IF #object_type='17' AND #transaction_type IN ('A','U')
BEGIN
Declare #CredLimit As nvarchar(250)
SET #CredLimit= (SELECT T0.CreditLine FROM OCRD T0
WHERE T0.CardCode=(SELECT CardCode FROM ORDR
WHERE DocEntry = #list_of_cols_val_tab_del)
IF (
SELECT (T0.DocTotal+T1.Balance)
FROM ORDR T0
INNER JOIN OCRD T1 ON T0.CardCode=T1.CardCode
WHERE DocStatus='O' AND T1.DocEntry=#list_of_cols_val_tab_del) > #CredLimit
BEGIN
Set #error = -1
SET #error_message = 'Business Partner is Over Credit Limit! Save this document as DRAFT, thank you'
END
END
The issue is that in the SET #CredLimit statement was checking if T0.CardCode was equal to #list_of_cols_val_tab_del, which is actually the DocEntry of the order. Actually, now that I look at it, you could even do something like
IF #object_type='17' AND #transaction_type IN ('A','U')
BEGIN
IF EXISTS (
SELECT T0.DocEntry
FROM ORDR T0
INNER JOIN OCRD T1 ON T0.CardCode=T1.CardCode
WHERE DocStatus='O'
AND T1.DocEntry=#list_of_cols_val_tab_del
AND (T0.DocTotal + T1.Balance) > T1.CreditLine)
BEGIN
Set #error = -1
SET #error_message = 'Business Partner is Over Credit Limit! Save this document as DRAFT, thank you'
END
END
In this second version, you completely ignore the unnecessary step of declaring a variable.

MySQL Stored procedure SELECT var wrong value after INSERT

I have a problem on MySQL stored procedure, already did another logic with IF THEN ELSE, but I still have problems which I cant understand...
The procedure consists on two user inputs: user_id and meet_id. The procedure define a variable called 'ue' which stores result of a bunch of validation (if user exists, if event exists, if event date is still valid, etc.).
After that, it does INSERT and UPDATE some data on multiple tables in IF THEN ELSE selector, and SELECT 1 (or 0) AS result depending of validation.
But my problem is: it always return me 0 as 'result', as if my validation variable was 0 when I do INSERT... And there is where things get weird, if I remove the INSERT [...]; line of the code, it returns me the value of validation correctly (1 or 0).
The code of the procedure is this one:
CREATE DEFINER=`nwouserf`#`localhost`
PROCEDURE `join_event`(IN `user_id` BIGINT(64), IN `event_id` INT)
NOT DETERMINISTIC MODIFIES SQL DATA SQL SECURITY DEFINER
begin
DECLARE ue INT;
SET ue = EXISTS(SELECT 1 FROM users WHERE fb_uid=user_id)
AND EXISTS(SELECT 1 FROM meetup WHERE meet_id=event_id)
AND EXISTS(SELECT 1 FROM meetup WHERE date > NOW() AND meet_id = event_id)
AND EXISTS(SELECT 1 FROM meetup WHERE meet_id = event_id AND participants <= max_participants)
AND NOT EXISTS(SELECT 1 FROM meetup_participation WHERE fb_uid = user_id AND meet_id = event_id);
IF ue = 1 THEN
INSERT INTO meetup_participation (fb_uid, meet_id) VALUES (user_id, event_id);
UPDATE users SET events_participated = events_participated + 1 WHERE fb_uid=user_id;
UPDATE meetup SET participants = participants + 1 WHERE meet_id=event_id;
SELECT 1 AS result;
ELSEIF ue = 0 THEN
SELECT 0 AS result;
ELSE
SELECT null AS result;
END IF;
end
Thanks in advance!
I have been stuck on this for a while now, and can not figure out why.
You should define OUT parameter. Add
", OUT result INT"
immediately after the last IN parameter.

MySQL procedure returning wrong value (INSERT SELECT confronting)

I'm completely new to MySQL, and have been bumping with some errors, but always I do find solutions, except for this one I can't understand how to get around it.
The following MySQL Procedure returns me a value if variable "ue" is 1 or 0 (a bunch of exists validation). The validation part (SET ue = EXISTS...) works without the rest of the code, as it should, the problem is not there. But when I do execute the command INSERT INTO SELECT, it does not work, it always return 0 as response, when it should be 1. These two lines are getting in confrontation with each other.
INSERT INTO meetup_participation SELECT user_id, event_id FROM DUAL WHERE ue=1;
SELECT ue AS response;
The procedure should add 'user id' and 'event id' into meetup_participation, and then update the row at 'users' corresponding to the user with that 'user id' to increment the 'events participated'. And it also UPDATE to increment the participation in the event with this 'event id'.
I am using the SET ue to validate things like, if user exists, if event does exists, if date of event is still valid, and if user is not already in this table. So I am passing this value as a boolean to INSERT INTO meetup_participation [...] WHERE ue = 1. After that, I do SELECT ue to inform validation returned true and procedure executed without problems.
Here is the full procedure.
CREATE DEFINER=`user`#`localhost` PROCEDURE `join_event`(IN `user_id` BIGINT(64), IN `event_id` INT) NOT DETERMINISTIC MODIFIES SQL DATA SQL SECURITY DEFINER
begin
DECLARE ue INT;
SET ue = EXISTS(SELECT 1 FROM users WHERE fb_uid=user_id) AND EXISTS(SELECT 1 FROM meetup WHERE meet_id=event_id) AND EXISTS(SELECT 1 FROM meetup WHERE date > NOW() AND meet_id = event_id) AND EXISTS(SELECT 1 FROM meetup WHERE meet_id = event_id AND participants <= max_participants) AND NOT EXISTS(SELECT 1 FROM meetup_participation WHERE fb_uid = user_id AND meet_id = event_id);
INSERT INTO meetup_participation SELECT user_id, event_id FROM DUAL WHERE ue=1;
UPDATE users SET events_participated = events_participated + 1 WHERE fb_uid=user_id AND ue=1;
UPDATE meetup SET participants = participants + 1 WHERE meet_id=event_id AND ue=1;
SELECT ue AS response;
end
Thanks in advance.
The INSERT statement is executed separately from the SET ue =... statement. I'm not sure what you are trying to accomplish, but the code makes no sense.
If you want to add records to meetup_participation based on the EXISTS tests applied to each record in the users table, you would need to apply the tests to each record in your SELECT statement as part of the INSERT.
There are also numerous syntax/grammar issues in the code as shown.
If you could provide an explanation of what you are trying to accomplish with the procedure, that might allow someone to suggest the right way to code the procedure.
Selecting ue will not tell you if the procedure completed without error. You should research mysql transactions and mysql error handling. http://www.mysqltutorial.org/mysql-error-handling-in-stored-procedures/ is a good starting point.
You might end up with something like this
drop procedure if exists p;
delimiter //
CREATE DEFINER=`root`#`localhost` PROCEDURE `p`(
IN `inue` int,
IN `user_id` BIGINT(64),
IN `event_id` INT
)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
begin
DECLARE ue INT;
declare exit handler for sqlexception
begin
rollback;
insert into errors (msg) select concat('error ' ,inue,',',user_id,',',event_id);
end;
set autocommit = 0;
#set ue = inue;
SET ue = EXISTS(SELECT 1 FROM users WHERE fb_uid=user_id)
AND EXISTS(SELECT 1 FROM meetup WHERE meet_id=event_id)
#AND EXISTS(SELECT 1 FROM meetup WHERE dt > NOW() AND meet_id = event_id)
AND EXISTS(SELECT 1 FROM meetup WHERE meet_id = event_id AND ifnull(participants,0) <= max_participants)
AND NOT EXISTS(SELECT 1 FROM meetup_participation WHERE fb_uid = user_id AND meet_id = event_id)
;
select ue;
if ue = 1 then
start transaction;
INSERT INTO meetup_participation SELECT user_id, event_id,user_id, event_id;
UPDATE users SET events_participated = ifnull(events_participated,0) + 1 WHERE fb_uid=user_id = user_id;
UPDATE meetup SET participants = ifnull(participants,0) + 1 WHERE meet_id = event_id ;
commit;
end if;
SELECT ue AS response;
end //
The error table looks like this
CREATE TABLE `errors` (
`msg` varchar(2000) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
Note I am not suggesting this is a solution appropriate to your site , you need to do the research and figure out what is best for you.