stored proc: if else statement inside case when - mysql

BEGIN
CASE x
WHEN 0 THEN (
IF thisIsAVariable = 'viewAll' THEN
SELECT id, fname FROM Persons WHERE 1
ELSE
SELECT id, fname FROM Persons WHERE id = '1111'
END IF
);
END CASE;
END
What is the correct syntax for ifelse statments inside casewhen statements?

we can use if inside the if to make code easy like below:
BEGIN
IF x = 0 THEN
IF thisIsAVariable = 'viewAll' THEN
SELECT id, fname FROM Persons WHERE 1;
ELSE
SELECT id, fname FROM Persons WHERE id = '1111';
END IF;
END IF;
END

just use IF-ELSE,
DELIMITER $$
CREATE PROCEDURE procName
BEGIN
IF x = 0 THEN
IF thisIsAVariable = 'viewAll' THEN
SELECT id, fname FROM Persons WHERE 1;
ELSE
SELECT id, fname FROM Persons WHERE id = '1111';
END IF;
ELSE
-- other codes if you have
END IF;
END $$
DELIMITER ;
I think when using CASE, the select statement should return only one value.

just try this one
BEGIN
CASE x
WHEN 0 THEN (
SELECT id, fname FROM Persons WHERE id = IF(thisIsAVariable = 'viewAll',1,'1111')
);
END CASE;
END

Related

Single Conditional Check Affecting Multiple (or All) Columns Inside a Single Row

What I'd like to accomplish, is affect multiple columns of all rows where e.g. column1 > 5 to have their values altered or replaced.
Is there any elegant way of performing this conditional check once (assuming it is a complex statement) and using its outcome for the columns using CASE / WHEN?
I understand that I can perform standard filtering using WHERE column1 > 5 and UNION of sorts, but I'd like to learn if there are any other options (maybe even MySQL specific) available.
Edit:
As an example:
SELECT
CASE
WHEN Country = 'UK' THEN CustomerId
ELSE '???'
END AS "CustomerId",
CASE
WHEN Country = 'UK' THEN City
ELSE '???'
END AS "City",
CASE
WHEN Country = 'UK' THEN Country
ELSE '???'
END AS "Country"
FROM Customers
As you can see, I'm using CASE WHEN Country = 'UK' multiple times here which I'd like to avoid.
You can use union all:
select c.customerid, c.city, c.country
from customers c
where country = 'UK'
union all
select '???', '???', '???'
from customers c
where country is null or country <> 'UK'
I think the elegant solution here is to have every column affected by column1 it's own transformation function;
DELIMITER $$
CREATE FUNCTION fn_transformation_for_column2(var_column1 INT)
RETURNS INT
BEGIN
IF (fn_condition(var_column1)) THEN
RETURN 1;
ELSE
RETURN 5;
END IF;
END;
DELIMITER ;
DELIMITER $$
CREATE FUNCTION fn_transformation_for_column3(var_column1 INT)
RETURNS INT
BEGIN
IF (fn_condition(var_column1)) THEN
RETURN 14;
ELSE
RETURN 51;
END IF;
END;
DELIMITER ;
based on the shared condition (which again can be a function):
DELIMITER $$
CREATE FUNCTION fn_condition(var_column1 INT)
RETURNS BOOLEAN
BEGIN
IF (var_column1 > 5) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END;
DELIMITER ;
Finally:
SELECT
fn_transformation_for_column2(t.column1) NewColumn2,
fn_transformation_for_column3(t.column1) NewColumn3,
...
FROM table t
;
Another would be to have the same transformation function for all the columns, and have the transormation handle it based on the given columntype parameter:
DELIMITER $$
CREATE FUNCTION fn_transformation_for_columns(var_column1 INT, var_column_no INT)
RETURNS INT
BEGIN
IF (var_column1 > 5) THEN
CASE var_column_no
WHEN 2 THEN
RETURN 1;
WHEN 3 THEN
RETURN 14;
ELSE
RETURN 0;
END CASE;
ELSE
CASE var_column_no
WHEN 2 THEN
RETURN 5;
WHEN 3 THEN
RETURN 51;
ELSE
RETURN 0;
END CASE;
END IF;
END;
DELIMITER ;
and then:
SELECT
fn_transformation_for_columns(t.column1, 2) NewColumn2,
fn_transformation_for_columns(t.column1, 3) NewColumn3,
...
FROM table t
;

MySQL Replace non-existent records with Not Found while using WHERE IN

How do I replace non-existent records with not found in the following query. Right now I'm just getting the records that are found.
SELECT CASE WHEN `Name` IS NOT NULL THEN `Name` ELSE 'Not Found' END AS Name
FROM `studentDetails`
WHERE `Transaction_ID` IN('496018490c1d5d60beb5', '77888f084c8a0e7578f5')
My input is
'496018490c1d5d60beb5',
'77888f084c8a0e7578f5'
What I'm getting is
Vinod Tonde
My desired output is
Not Found
Vinod Tonde
The Database looks like
I think what you want is this:
SELECT Transaction_ID, CASE WHEN count(*)>0 THEN `Name` ELSE 'Not Found' END AS Name
FROM `studentDetails`
WHERE `Transaction_ID` IN('496018490c1d5d60beb5', 'b6836a07a3c49af6187f')
group by Transaction_ID
OR, using this you could also try:
SELECT IFNULL(Name, 'Not Found') AS Name
FROM (SELECT '496018490c1d5d60beb5' as col
union all
SELECT 'b6836a07a3c49af6187f') temp_table
LEFT JOIN studentDetails
ON temp_table.col=studentDetails.Transaction_ID collate utf8mb4_unicode_ci
Try this:
UPDATE `studentDetails` SET `Name` = 'Not Found' WHERE (`Name` IS NULL OR `Name` = '') AND `Transaction_ID` IN('496018490c1d5d60beb5', 'b6836a07a3c49af6187f')
You can add a few more alternatives to your case
SELECT CASE
WHEN Name IS NULL THEN 'Not Found'
WHEN length(trim(Name)) = 0 THEN 'Not Found'
ELSE Name
END AS Name
FROM studentDetails
WHERE Transaction_ID IN('496018490c1d5d60beb5', 'b6836a07a3c49af6187f')
Edit
Since it seems that one of those two transaction_id doesn't exist in the database at all, you probably need something like this instead
select coalesce(t2.Name, 'Not Found') as Name
from (select '77888f084c8a0e7578f5' as trans union all select '496018490c1d5d60beb5') t1
left join
studentDetails t2
on t1.trans = t2.Transaction_ID
Create a table for the ids to search:
CREATE TABLE ids (id VARCHAR(30));
Create a procedure to split a list of ids separated by a ',' and insert them into the ids table:
CREATE PROCEDURE split_id_list(IN input VARCHAR(300))
BEGIN
DECLARE tot_length int;
DECLARE sub_length int;
my_loop: LOOP
SET tot_length = CHAR_LENGTH(input);
INSERT INTO ids (id) VALUES(SUBSTRING_INDEX(input, ',', 1));
SET sub_length = CHAR_LENGTH(SUBSTRING_INDEX(input, ',', 1))+2;
SET input = MID(input, sub_length, tot_length);
IF input = '' THEN
LEAVE my_loop;
END IF;
END LOOP my_loop;
END;
Create a procedure to generate view containing the results:
CREATE PROCEDURE idsNames(IN id_list VARCHAR(500))
BEGIN
DECLARE a INT;
DECLARE cur1 CURSOR for select count(*) FROM ids;
OPEN cur1;
FETCH cur1 into a;
IF a > 0
THEN DELETE FROM ids;
END IF;
CLOSE cur1;
call split_id_list(id_list);
CREATE OR REPLACE VIEW RESULTS(r_id,r_name) AS
(SELECT ids.id, CASE WHEN Name IS NULL then 'NotFound' ELSE Name END
FROM studentDetails
RIGHT JOIN ids
ON studentDetails.Transaction_ID = ids.id);
END;
Once the table and the procedures are created, each time you want to execute them, just execute the procedure with the required ids and a select from the view:
CALL idsNames('496018490c1d5d60beb5,b6836a07a3c49af6187f');
SELECT r_name FROM RESULTS;

Display 'Present' if Row exists, display 'Missing' if'otherwise

The code below checks if a row is returned. If true, it should display 'PRESENT' ELSE 'MISSING'.
I have tried values that will return either 0 or 1 but both returns 'MISSING'. What could I have missed here.
DELIMITER //
CREATE PROCEDURE UserCheck (
IN p_ACCEPTED_BY VARCHAR(32))
BEGIN
DECLARE isPresent INT(10);
SELECT EXISTS (
SELECT *
FROM ETOOLS.UserTermsAndConditions
WHERE ACCEPTED_BY = 'p_ACCEPTED_BY') INTO isPresent;
IF isPresent = 1 THEN
SELECT 'PRESENT';
ELSE
SELECT 'MISSING';
END IF;
END //
DELIMITER ;
remove ' ' on parameter. should be:
SELECT EXISTS (
SELECT *
FROM ETOOLS.UserTermsAndConditions
WHERE ACCEPTED_BY = p_ACCEPTED_BY) INTO isPresent;

How come this codes error? SQL Error code 1109: Unknown table 'o' in field list

When i run this code, it gives me error. From this code, there's several task to do:
(1) update tble customer by setting the address to '90 TYT' if c_id= 1
(2) view order_no,status,c_id,item_total remarks.
(3) if item_total 0, then update table order_status by setting remarks = 'UNAVAILABLE', else select order_no,status,item_total,remarks where status = 'waiting'.
Please help me fix the error. I'm new to SQL.
#drop procedure if exists usp_GetAnything;
delimiter //
create procedure usp_GetAnything()
begin
select c_id,lname,address,city
from customer;
update customer
set address = '90 TYT'
where c_id = 1;
select o.order_no,o.o_status,c.c_id,o.item_total,o.remarks
from customer c, order_status o
where c.c_id=o.c_id;
if (o.item_total > 0) then
update order_status o
set remarks = 'UNAVAILABLE'
where order_no > '123';
else
select order_no,o_status,item_total,remarks
from order_status
where o_status = 'waiting';
end if;
end
It's failing on the line:
if (o.item_total > 0)
o is unidentified outside of the previous select clause including all the selected variables.
In order to use the results that returned from the previous select you should select ... INTO...
(select the result arguments into declared local variables).
You can find here the following example:
DELIMITER //
CREATE PROCEDURE `proc_WHILE` (IN param1 INT)
BEGIN
DECLARE variable1, variable2 INT;
SET variable1 = 0;
WHILE variable1 < param1 DO
INSERT INTO table1 VALUES (param1);
SELECT COUNT(*) INTO variable2 FROM table1;
SET variable1 = variable1 + 1;
END WHILE;
END //
You can see that variable1 and variable2 are declared in the beginning of the procedure and later on used with select ... INTO ....

mysql stored procedure error (1172, 'Result consisted of more than one row')

When trying to run the following stored procedure from django, I get an OperationError (1172, 'Result consisted of more than one row') Any idea what I might be doing wrong?
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `UpdatePrices`(IN storeId int, IN bottleSize VARCHAR(50))
BEGIN
DECLARE amount DECIMAL(10,2); DECLARE isCustom INT DEFAULT 0;
DECLARE changeType VARCHAR(50) DEFAULT 'State'; DECLARE updateType INT DEFAULT 0;
IF bottleSize = '1000 Ml' THEN
SELECT S1000IncreaseChoices INTO changeType FROM store_store WHERE StoreID = storeId;
IF changeType = 'State' THEN
SELECT updateType = 0;
END IF;
IF changeType = 'Flat' THEN
SELECT S1000IncreaseAmount INTO amount FROM store_store WHERE StoreID = storeId;
SELECT updateType = 1;
END IF;
IF changeType = 'Percent' THEN
SELECT 1 - S1000IncreaseAmount/100 INTO amount FROM store_store WHERE StoreID = storeId;
SELECT updateType = 2;
END IF;
END IF;
IF updateType = 0 THEN
update store_storeliquor SL
inner join liquor_liquor LL
on liquorID_id = id
set StorePrice = ShelfPrice
where BottleSize = bottleSize
and storeID_id = storeId
and custom = 0;
END IF;
IF updateType = 1 THEN
update store_storeliquor SL
inner join liquor_liquor LL
on liquorID_id = id
set StorePrice = OffPremisePrice + amount
where BottleSize = bottleSize
and storeID_id = storeId
and custom = 0;
END IF;
IF updateType = 1 THEN
update store_storeliquor SL
inner join liquor_liquor LL
on liquorID_id = id
set StorePrice = OffPremisePrice / amount
where BottleSize = bottleSize
and storeID_id = storeId
and custom = 0;
END IF;
END
I'm not sure if it matters, but I initiate the stored procedure like so:
def priceupdate(request, store_id):
cursor = connection.cursor()
cursor.callproc("UpdatePrices", (store_id, '1000 ML'))
cursor.close()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
Your SELECT...INTO queries give result sets with more then one record. The WHERE filters are incorrect - they compare two the same values StoreID = storeId. Rename IN storeId int parementer to another name. For example - IN storeId_param int
The query will be like this -
SELECT S1000IncreaseChoices INTO changeType FROM store_store WHERE StoreID = storeId_param;
This is a Bug and you need to apply something like that:
SELECT id,data INTO x,y FROM test.t1 LIMIT 1;