stored procedure in SQL - mysql

I have a stored procedure that should check if an artist being added is in the Allowed Nationality table, but it doesn't work. The code inserts the artist whether they are in the Allowed Nationality table or not. Can anyone tell me what I have done wrong?
DELIMITER //
CREATE PROCEDURE `InsertNewArtistCheck`
(IN newLastName Char(25),
IN newFirstName Char(25),
IN newNationality Char(30),
IN newDateOfBirth Numeric(4),
IN newDateDeceased Numeric(4))
BEGIN
DECLARE varRowCount Int;
SELECT Nation INTO varRowCount
FROM ALLOWED_NATIONALITY
WHERE Nation = newNationality;
IF (varRowCount < 0)
THEN
ROLLBACK;
SELECT 'Nationality Not Allowed' AS ErrorMessage;
END IF;
INSERT INTO ARTIST (LastName, FirstName, Nationality,
DateOfBirth, DateDeceased)
VALUES (newLastName, newFirstName, newNationality,
newDateOfBirth, newDateDeceased);
SELECT 'New artist data added to database' AS InsertStatus;
END//
DELIMITER ;

Try the following changes:
DECLARE varRowCount Int;
SELECT count(*) INTO varRowCount
FROM ALLOWED_NATIONALITY
WHERE Nation = newNationality;
IF (varRowCount < 1)
THEN
ROLLBACK;
SELECT 'Nationality '+newnationality+' not Allowed' AS ErrorMessage;
RETURN
END IF;
You are trying to put a character value (NATION) into a numeric variable (varRowCount). What you really want is to determine the number of nations (hopefully 1) which match the new artist's nation. You also don't need the ROLLBACK statement, since the stored procedure has not done anything it needs to "undo"

WIll be closed, still....
See this line:
IF (varRowCount < 0)
Tell me under what conditions you think SQL Server will ever return a NEGATIVE number of rows?
Should be equals 0, not smaller than.

Related

mysql procedure with if condition

I'm in my first databases class and I'm trying to write a conditional block for a mysql procedure.
This is the procedure:
delimiter //
CREATE PROCEDURE add_ascent(IN cid INT, IN pid INT)
BEGIN
DECLARE count_ascents INT;
SET count_ascents = 0;
SELECT COUNT(`cid`) INTO count_ascents FROM ascents WHERE `cid`=cid AND `pid`=pid;
IF count_ascents < 1 THEN
INSERT INTO ascents (`cid`, `pid`) VALUES (cid, pid);
UPDATE climbers SET climbers.ascents = climbers.ascents + 1 WHERE climbers.id=cid;
UPDATE problems SET problems.ascents = problems.ascents + 1 WHERE problems.id=pid;
END IF;
END;
//
delimiter ;
The goal of the procedure is to only perform the insert and updates if the (cid, pid) pair is not in the the ascents database. After testing, the program doesn't seem to go into the if block at all.
FYI, you might want to consider using an UPSERT, instead of "select/if/insert". For example, mySQL offers INSERT ON DUPLICATE KEY UPDATE.
Here, I suggest:
giving your parameters a DIFFERENT name than the column name, for example iCid and iPid, then
Typing SELECT COUNT(cid) INTO count_ascents FROM ascents WHERE cid=iCid AND pid=iPid and checking the result.

How to add salary from two tables in stored procedure

I want to add the salary from two tables in stored procedure on the basis of id column:
DDl:
create table salary1 (id varchar(20), salary varchar(20));
create table salary2 (id varchar(20), salary varchar(20));
DML:
insert into salary1 values('1', '100');
insert into salary1 values('2', '200');
insert into salary2 values('1', '10');
insert into salary2 values('2', '10');
Database: mysql
Output should like this:
id total_sal
1 110
2 210
My stored procedure look like:
CREATE PROCEDURE totalSal()
BEGIN
DECLARE tbl1_id varchar(30);
DECLARE tbl1_sal varchar(30);
DECLARE tbl2_id varchar(30);
DECLARE tbl2_sal varchar(30);
DECLARE total_sal varchar(30);
DECLARE c1 CURSOR FOR SELECT * FROM salary1;
DECLARE c2 CURSOR FOR SELECT * FROM salary2;
-- Open first cursor
OPEN c1;
LOOP
FETCH c1 INTO tbl1_id, tbl1_sal;
-- Open second cursor
OPEN c2;
LOOP
FETCH c2 INTO tbl2_id, tbl2_sal;
IF tbl1_id = tbl2_id THEN
set total_sal := tbl1_sal + tbl2_sal;
ELSE
set total_sal := tbl_sal;
END IF;
END LOOP;
CLOSE c2;
END LOOP;
CLOSE c1;
end $$
It got's successfully compiled, but when i am running the procedure i am getting the below error:
ERROR 1329 (02000): No data - zero rows fetched, selected, or processed
I have also used the DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; in my procedure. but still my problem is unresolved.
If someone can solve this problem in oracle, that would also help me.
Note : I cannot perform join operation on these tables. Because of a few performance issues.
Thanks in advance !!!
Solution 1:
Using collection and only one iteration of 2 loop
You should consider to fix your performance issue on join. Performing loop is slower than a set base approach in most case.
If I follow your logic, what you realy want is to loop trough all the salary2 table for each salary1 row in order to found the right ID => millions of loop.
You can consider doing 2 separated loop and store data inside and indexed array. ( the key will be the tlb1_id).
If the key exist : sum the salary values, if not exist insert it inside the array.
At the end of the procedure, just select the array as table.
Solution 2:
Using a join on integer indexed columns
you can add a new integer column on each table
Populate this column with the casted value of the ID column
Add an index on these columns on each tables
After that you will be able to perform a join
Have a look at this fiddle http://sqlfiddle.com/#!9/c445de/1 , it can be time consuming to perform theses step and disk space consumuming to add a new columns and indexes but the join operation may be faster than before.
You can do something like this... I have moved the second cursor inside the loop so that it only goes over the id's from table 1. This should help the logic for the procedure but still I would recommend trying to figure out how to fix the join to get the results as that seems like an easier way and should be much faster if done correctly.
CREATE PROCEDURE totalSal()
BEGIN
DECLARE tbl1_id varchar(30);
DECLARE tbl1_sal varchar(30);
DECLARE tbl2_id varchar(30);
DECLARE tbl2_sal varchar(30);
DECLARE total_sal varchar(30);
DECLARE c1 CURSOR FOR SELECT * FROM salary1;
-- Open first cursor
OPEN c1;
LOOP
FETCH c1 INTO tbl1_id, tbl1_sal;
SELECT COUNT(*) INTO v_rowcount FROM salary2 WHERE id = tbl1_id;
IF v_rowcount > 0 THEN
Begin
DECLARE c2 CURSOR FOR SELECT * FROM salary2 WHERE id = tbl1_id;
-- Open second cursor
OPEN c2;
LOOP
FETCH c2 INTO tbl2_id, tbl2_sal;
IF tbl1_id = tbl2_id THEN
set total_sal := tbl1_sal + tbl2_sal;
ELSE
set total_sal := tbl_sal;
END IF;
END LOOP;
CLOSE c2;
END IF;
END
END LOOP;
CLOSE c1;
end $$
Well you asked for an answer without JOIN, but that seemed arbitrary, so here's an answer with JOIN.
SELECT
sums1.id
, S1Sum + S2Sum AS SalarySum
FROM (SELECT id, SUM(CAST(salary AS int)) AS S1Sum
FROM salary1
GROUP BY id) sums1
JOIN (SELECT id, SUM(CAST(salary AS int)) AS S2Sum
FROM salary2
GROUP BY id) sums2
ON sums1.id = sums2.id
I am guessing your performance is bad because all of your columns are varchar when they should be int or numeric. But we don't have much to go on so hopefully this helps you come to a solid solution.
Also the post was edited to add both MySQL and Oracle tags so it's difficult to determine what the syntax should be...

MYSQL "create match on X date if team A and team B are free" using procedures & transactions

So I am trying to learn a bit more in MySQL, I was given this exercise to work on procedures & transactions. it reads as follows:
"Create a MySQL procedure named scheduleMatch that schedules a match in a tournament.
The procedure should use the following parameters:
Tournament Name
Name of Home Team
Name of Away Team
Date of Match
The procedure works by first scheduling (creating) a match on the given date between the home and the away teams. In order to do this the procedure must make sure both teams are free on the given date. "
And then we are to use this syntax to call it.
CALL scheduleMatch(‘Tournament1’, ‘TeamA’, ’TeamB’, ‘2015-11-08’);
delimiter $$
create procedure schedulematch(IN tournamentName_param varchar(40), IN HomeTeamId_param varchar(40),
IN AwayTeamId_param varchar(40),IN matchDate_param date)
BEGIN
DECLARE success_entry BOOL DEFAULT TRUE;
SET success_entry = TRUE;
start Transaction;
IF NOT EXISTS (select * from match where MatchDate = MatchDate_Param AND HomeTeamId = HomeTeamId_Param AND AwayTeamId = AwayTeamId_Param) THEN
insert into match values
(NULL, matchDate_Param, fetch_teamID(HomeTeamId_param),fetch_teamID(AwayTeamId_param), 0, 0, 0 , 0);
SELECT 'match Added ' AS MESSAGE;
commit;
else
rollback;
end if;
end$$
delimiter ;
CALL scheduleMatch(‘Tournament1’, ‘TeamA’, ’TeamB’, ‘2015-11-08’);
I thought what I have above would have worked, but it still runs the insert statement. Any help would be appreciated!
I am looking for a bit of education on this, not just the answer!
You can change that IF NOT EXISTS part using INSERT INTO .. SELECT FROM construct and using WHERE NOT EXISTS like
insert into `match`
SELECT NULL, matchDate_Param, fetch_teamID(HomeTeamId_param),
fetch_teamID(AwayTeamId_param), 0, 0, 0 , 0,
'match Added ' AS MESSAGE
FROM DUAL
WHERE NOT EXISTS (select 1 from `match`
where MatchDate = MatchDate_Param
AND HomeTeamId = HomeTeamId_Param
AND AwayTeamId = AwayTeamId_Param);

MySQL stored procedure if statement not working

I have the following stored procedure in MySQL
CREATE DEFINER=`test_db`#`%` PROCEDURE `ADD_ATTENDANCE`(IN `programID` INT, IN `clientID` INT, IN `insDate` DATETIME, IN `updDate` DATETIME, IN `insUser` INT, IN `updUser` INT, IN `lessonDate` DATE, IN `lessonTime` TIME)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'Add attedance to my calendar'
BEGIN
DECLARE max_sub, availability INT;
DECLARE cursor_max_sub CURSOR FOR SELECT max_sub FROM app_lesson WHERE id = programID;
DECLARE cursor_availability CURSOR FOR SELECT count(*) FROM attendance WHERE program_id = programID AND lesson_date = lessonDate AND lesson_time = lessonTime;
OPEN cursor_max_sub;
OPEN cursor_availability;
read_loop: LOOP
FETCH cursor_max_sub INTO max_sub;
FETCH cursor_availability INTO availability;
IF (availability < max_sub) THEN
insert into attendance (program_id, client_id, ins_date, upd_date, ins_user, upd_user, lesson_date, lesson_time)
values (programID, clientID, insDate, updDate, insUser, updUser, lessonDate, lessonTime);
LEAVE read_loop;
ELSE
insert into attendance_hold (program_id, client_id, ins_date, upd_date, ins_user, upd_user, lesson_date, lesson_time)
values (programID, clientID, insDate, updDate, insUser, updUser, lessonDate, lessonTime);
END IF;
END LOOP;
CLOSE cursor_max_sub;
CLOSE cursor_availability;
END;
Even though the cursor_max_sub is equal to 6 and the cursor_availability is equal to 4 my procedure always executes the else insert statement. Can you please help me out?
Thanks!!!
OK that was tricky... For some reason when i change the max_sub variable into maxNumberOfSubscription everything worked perfectly... Is max_sub some kind of reserved key word for MySQL or there was a complication because my variable had the same name with the returned field of select statement?

sql if statement in store procedure

For some reason MYSQL will not let me create this procedure, can anybody see what the problem is?
It works if I remove the IF statement but to me the if statement looks ok.
delimiter $$
create procedure add_new_room(IN buildingID INT,
IN inName TEXT,
IN inWeeks INT,
IN inAnnual TEXT,
IN inWeekly TEXT)
BEGIN
DECLARE roomnameid INT;
DECLARE roomcount INT;
SELECT count(roomID) from tblRooms WHERE roomName = inName into roomcount;
if roomcount = 1 then
SELECT roomID from tblRooms
WHERE roomName = inName into roomnameid;
INSERT INTO tblAccommRoom
(roomWeeks,roomID,accommodationID,roomWeeklyRent, roomAnnualRent)
VALUES (inWeeks,roomnameid,buildingID,inWeekly, inAnnual);
else
INSERT INTO tblRooms (roomName) VALUES inName;
INSERT INTO tblAccommRoom
(roomWeeks, roomID, accommodationID, roomWeeklyRent, roomAnnualRent)
VALUES (inWeeks,LAST_INSERT_ID(),buildingID,inWeekly, inAnnual);
end if;
END
I would use a CASE WHEN statement instead of the IF statement, which allows the code to work a little more universally with MS SQL and MySQL.
CASE WHEN roomcount = 1 THEN...ELSE...END
I don't do a lot of work with MySQL, but I also typically see IF statements contained within parentheses and commas utilized rather than spelling out THEN and ELSE.
IF(condition,then statement,else statement)
Try changing the SELECT to this:
SELECT count(roomID) into roomcount from tblRooms WHERE roomName = inName;
then, you should be able to use 'roomcount' later on.