Stored procedure using if statement - mysql

I have here stored procedure:
delimiter //
create procedure insert(p int, n varchar(10), d date, q int)
begin
select pname if(pname!=n)
then
insert into prod(p,n,d,q)values(p,n,d,q)
else quant=quant + q;
from prod;
end;
//
This stored procedure will add records to the table prod if pname and n are not equal ELSE if they are equal, the quant will be updated and added by the value of q. This idea is not working can you help me? How to achieve this one?

....
BEGIN
DECLARE p CHAR DEFAULT NULL;
SELECT pname FROM prod WHERE pname = n LIMIT 1 INTO p FOR UPDATE;
IF(p) THEN
UPDATE prod SET quant = quant + q WHERE pname = n;
ELSE
INSERT INTO prod(p,n,d,q) values(p,n,d,q);
END IF;
END;
There are simpler ways to do it if you have a UNIQUE key on pname in prod.

Related

Stored Procedure updates two rows

DELIMITER //
CREATE OR REPLACE PROCEDURE GET_USER_PNTS(USER_ID INT , PNTS INT, QNT INT)
BEGIN
DECLARE x INT DEFAULT 1;
DECLARE TEMP_GIFT_ID INT;
UPDATE USR_PNT_SUMM SET USD_PNTS = USD_PNTS + PNTS WHERE USER_ID = 1;
COMMIT;
END //
DELIMITER ;
The above stored procedure updates two rows - one for user_id = 1 and the other one for userid 0. I dont understand why!
This is how I call the stored procedure -
CALL GET_USER_PNTS(1, 1, 1)
Please let me know why the user_id 0 is also getting updated.
P.S
1. I am using MariaDB.
2. UserID 0 is what I had manually added in the table. In pratice there won't be any 0 user_id. But even then, the row should not have been updated.
Please rename your parameters:
CREATE OR REPLACE PROCEDURE GET_USER_PNTS(L_USER_ID INT , L_PNTS INT, L_QNT INT)
BEGIN
DECLARE x INT DEFAULT 1;
DECLARE TEMP_GIFT_ID INT;
UPDATE USR_PNT_SUMM SET USD_PNTS = USD_PNTS + L_PNTS WHERE USER_ID = L_USER_ID;
COMMIT;
END //
Probably USER_ID = USER_ID is treated as true.

How do I use a recursive procedure in a loop in MySQL

I have an employees table with demographics data. This table has two fields I need: Employee ID and Manager ID. I need to build a join table that would look like this:
Employee IDManager ID
1 2
1 3
1 4
2 3
2 4
So I need the join table to show, for each employee, all the people above them. In case of employee 1 his direct manager is 2, his manager's manager is 3 and his manager's manager's manager is 4.
I have a MySQL procedure that seems to be working when called for an employee:
CREATE PROCEDURE chainReaction (IN employee_id int, IN orig_id int)
BEGIN
DECLARE manager_id int default NULL;
SET ##SESSION.max_sp_recursion_depth = 255;
SELECT ManagerID
INTO manager_id
FROM employees
WHERE EmployeeID = employee_id;
IF( manager_id is not null) THEN
INSERT INTO joinTable(EmpID, SupID) VALUES(
orig_id,manager_id
);
CALL chainReaction(manager_id, orig_id);
end if;
END;
Problem 1:
When calling chainReaction it looks like I need to provide the employee ID twice to the procedure because otherwise the original employee ID is 'lost' and the resulting inserts for employee 1 look like this:
Employee IDManager ID
1 2
2 3
4 4
So the Employee ID doesn't stay fixed to 1 as I needed it. Again, this procedure works when called as it is now: chainReaction(1,1);
But here's problem 2:
I have some code to loop through all rows in the employee table and call chainReaction on them:
CREATE PROCEDURE RowPerRow ()
BEGIN
DECLARE n int default 0;
DECLARE i int default 0;
DECLARE employee_id int default null;
SELECT COUNT(*) FROM employees INTO n;
SET i=0;
WHILE i<n DO
SELECT EmployeeID FROM employees WHERE LIMIT i,1 INTO employee_id;
CALL chainReaction(employee_id,employee_id);
END WHILE;
END;
The problem is that if I call this RowPerRow() procedure the employee column in the join table is stuck to the first employee ID no matter what row is being processed.
Looks like my procedures work just fine, what I was missing in the RowPerRow procedure is incrementing the counter (SET i = i + 1;). Here's the code fixed.
CREATE PROCEDURE RowPerRow ()
BEGIN
DECLARE n int default 0;
DECLARE i int default 0;
DECLARE employee_id int default null;
SELECT COUNT(*) FROM employees INTO n;
SET i=0;
WHILE i<n DO
SELECT EmployeeID FROM employees WHERE LIMIT i,1 INTO employee_id;
CALL chainReaction(employee_id,employee_id);
SET i = i + 1;
END WHILE;
END;

Loop items in list of user defined table types

I have simple table with 2 columns CarId int, primary key and CarName, varchar.
I need to create a stored procedure which accepts a list of cars. If car with CarId doesn't exist, I want to insert that car, and if already exists, I want to update it.
I created a user-defined table type CarType:
CREATE TYPE dbo.CarType
AS TABLE
(
CARID int null,
CARNAME varchar(800) not null,
);
and stored procedure InsertCars:
CREATE PROCEDURE dbo.InsertCars
#Cars AS CarType READONLY
AS
DECLARE #CarCount INT = 0;
DECLARE #Counter INT = 0;
BEGIN
SET #CarsCount = (SELECT COUNT(CarId) FROM #Cars);
WHILE(#Counter < #CarsCount)
BEGIN TRY
--how get item from list Cars?
#CurrentCar = Cars(#Counter)
IF EXISTS(SELECT 1 FROM Cars WHERE CarsId = CurrentCar.CarId)
--if doesn’t exist insert
BEGIN
INSERT INTO CARS(CARID, CARNAME)
SELECT * FROM #CurrentCar;
END
ELSE
BEGIN
--if exist update
END
END
SET #Counter= #Counter + 1;
END TRY
BEGIN CATCH
Print (ERROR_MESSAGE());
END CATCH
END
I don't know how get current car in loop from list of cars (parameter Cars in the stored procedure).
Or some elegant solution for this problem.
It seems you may get rid of loop here:
CREATE PROCEDURE dbo.InsertCars
#Cars AS CarType READONLY
AS
BEGIN
SET NOCOUNT ON;
UPDATE c
SET c.CARNAME = c2.CARNAME
FROM Cars c
JOIN #Cars c2 on c2.CARID = c.CARID;
INSERT INTO Cars(CARID, CARNAME)
SELECT c.CARID, c.CARNAME
FROM #Cars c
WHERE NOT EXISTS (SELECT 1 FROM Cars WHERE CARID = c.CARID);
END
or (using merge construct):
CREATE PROCEDURE dbo.InsertCars
#Cars AS CarType READONLY
AS
BEGIN
SET NOCOUNT ON;
MERGE Cars AS target
USING (SELECT CARID, CARNAME FROM #Cars) AS source (CARID, CARNAME)
ON (target.CARID = source.CARID)
WHEN MATCHED THEN
UPDATE SET CARNAME = source.CARNAME
WHEN NOT MATCHED THEN
INSERT (CARID, CARNAME)
VALUES (source.CARID, source.CARNAME);
END

Mysql Function returns Null always

I have a function in mysql like below:
DELIMITER $$
CREATE DEFINER=root#localhost FUNCTION fnGetDropDownValue(
itemValue varchar(300),
DropDownId int,
CId int
) RETURNS int(11)
BEGIN
DECLARE listId int;
SELECT ListID into listId FROM DropDownListValues WHERE LOWER(ListValue) = LOWER(itemValue) AND DropDownListID = DropDownId AND (ClientId = 0 OR ClientId = CId);
RETURN listId;
END$$
But it always returns Null values when I use
SELECT fnGetDropDownValue('General', 24, 18);
I don't know what I am doing wrong :(
After having the case sensitive issue with mysql columns I used to have variable names to start with _ to avoid it messing with column names. Now the stored procedure looks like this:
DELIMITER $$
CREATE DEFINER=root#localhost FUNCTION fnGetDropDownValue(
itemValue varchar(300),
DropDownId int,
CId int
) RETURNS int(11)
BEGIN
DECLARE _listId int;
SELECT ListID into _listId FROM DropDownListValues WHERE LOWER(ListValue) = LOWER(itemValue)
AND DropDownListID = DropDownId AND (ClientId = 0 OR ClientId = CId);
RETURN _listId;
END$$
This way it will work on any platform and it may be useful for others.

MySQL INSERT WHERE a variable is not duplicated

I have some troubles with DECLARE, CALL function and a IF settelment. What i have so far is:
CREATE PROCEDURE number_of_projects(project_name VARCHAR)
BEGIN
DECLARE variable INT;
SET variable = 4;
SELECT variable;
SELECT count(project_id) FROM atm_projects WHERE project_name = variable;
END
IF number_of_projects("PROJECT NAME") = 0
THEN
INSERT INTO atm_projects(project_id,project_name,added_from_mti)
VALUES (project_id,'PROJECT NAME',1)
ENDIF
The main goal is to insert a row into a table where project_name is not duplicated.
I could change project_name to an UNIQUE key but please tell me what is wrong with my code, an how can i fix this?
I need to learn how a PROCEDURE, CALL procedure, IF works.
try:
CREATE PROCEDURE number_of_projects(project_name VARCHAR(255))
BEGIN
DECLARE var_project_no INT;
SET var_project_no = 0;
SELECT var_project_no;
SELECT count(project_id) INTO var_project_no FROM atm_projects WHERE var_project_name = 4;
IF var_project_no = 0
THEN
INSERT INTO atm_projects(project_id,project_name,added_from_mti)
VALUES (project_id,'PROJECT NAME',1)
END IF;
END;
You have declared project_name to varchar without specifying the length. Change it to varchar(100)
CREATE PROCEDURE number_of_projects(project_name VARCHAR(255))
BEGIN
if NOT exists(SELECT Top 1 1 FROM atm_projects WHERE var_project_name = 4)
BEGIN
INSERT INTO atm_projects(project_id,project_name,added_from_mti)
Select project_id,project_name ,1
END
END;