MYSQL: IF statement to find a null column in n rows - mysql

I'm trying to use an IF statement to find out if any row where the primary key = copy_code has a column return = null and then I would like to do something if it is.
IF ((SELECT `return` FROM loan
WHERE `code` = copy_code AND `return` IS NULL) IS NULL THEN
do something
END IF;
I'm not getting any errors but when I insert data I don't get the correct results.
How can I achieve this?

set delimiter //
create procedure foo as
begin
declare #variable int
SELECT count(*) INTO #variable FROM loan
WHERE `code` = copy_code AND `return` IS NULL;
if (#variable)
begin
... do something
end
end//
set delimiter ;

Related

Mysql error nested arithmetic in select

When i am trying to execute this procedure it is showing an error.
USE `metro`;
DROP procedure IF EXISTS `transaction`;
DELIMITER $$
USE `metro`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `transaction`(
IN amount_p INT,
IN id_in INT,
IN id_out INT,
IN uidd INT
)
BEGIN
DECLARE uide INT;
DECLARE amt INT;
DECLARE NOW_AMT INT DEFAULT 0;
SELECT `amount` INTO amt FROM metro.wallet WHERE `uid`=uide;
INSERT INTO metro.transactions(`amount_deducted`,`time`,`station_id_in`,`station_id_out`,`uid`)
VALUES (amount_p,now(),id_in,id_out,uid);
SELECT uidd INTO uide;
SELECT uide;
SET NOW_AMT:=#amt+amount_p;
SELECT amt;
UPDATE metro.wallet SET `uid`=uide,`amount`=NOW_AMT;
END$$
DELIMITER ;
wallet is a table with uid and amount column.
Error code 1048, SQL state 23000: Column 'amount' cannot be null
Line 1, column 1
Execution finished after 0 s, 1 error(s) occurred.
Execution :
call metro.transaction(112,1,1,1);
Perhaps wrap your AMOUNT in a case statement where you can return a default if it is NULL.
SELECT case when `amount` is NULL then '' else `amount` END as `amount` INTO amt FROM metro.wallet WHERE `uid`=uide;

Stored procedure with recursive call using mysql

enter image description hereget legside from binary
I have tried using stored procedure with recursive call. i need to display relevant name based on emp_name based on leg1
but it showing error like #1414 - OUT or INOUT argument 2 for routine sample.getVolume is not a variable or NEW pseudo-variable in BEFORE trigger
Here is my code,
DELIMITER $$
CREATE PROCEDURE getVolume( IN param_name VARCHAR(255), OUT result VARCHAR(255 ))
BEGIN
SELECT val INTO result FROM employee WHERE emp_name = param_name ;
IF result IS NULL THEN
select result;
ELSE
CALL getVolume(result, '');
END IF;
END $$
DELIMITER ;
SET ##GLOBAL.max_sp_recursion_depth = 255;
SET ##session.max_sp_recursion_depth = 255;
call getVolume('new', #result);
select #result;
The answer of #Shadow is correct. Here a practical example that can help you:
DELIMITER //
DROP TABLE IF EXISTS `employee`//
DROP PROCEDURE IF EXISTS `getVolume`//
CREATE TABLE `employee` (
`emp_name` VARCHAR(255),
`val` VARCHAR(255)
)//
INSERT INTO `employee` (`emp_name`, `val`)
VALUES
('demo', 'new'),
('new', 'd.new'),
('d.new', 'view'),
('view', 'hello'),
('hello', NULL)
//
CREATE PROCEDURE `getVolume`(
IN `param_name` VARCHAR(255),
OUT `result` VARCHAR(255)
)
BEGIN
DECLARE `next_param_name` VARCHAR(255);
SELECT `val` INTO `next_param_name`
FROM `employee`
WHERE `emp_name` = `param_name`;
IF `next_param_name` IS NULL THEN
SET `result` := `param_name`;
ELSE
-- CALL `getVolume`(`result`, '');
CALL `getVolume`(`next_param_name`, `result`);
-- SET `result` := CONCAT(`param_name`, ',', IFNULL(`result`, ''));
END IF;
END//
DELIMITER ;
SQL Fiddle demo
The problem is that when you call getResult() within getresult, you pass an empty string constant as a parameter:
CALL getVolume(result, '');
Declare a variable instead and pass that as a parameter. After the getVolume call do not forget to concatenate what is returned by getVolume to the result variable with a separator character. Are you sure that 255 characters will be enough to hold all values?

Check if a row exists inside a MySQL function

In my user table the IDs user_id are randomly generated by the following functions:
DELIMITER #
CREATE FUNCTION GenerateRandomUserID()
RETURNS CHAR(15)
BEGIN
DECLARE user_id CHAR(15) DEFAULT '';
WHILE LENGTH(user_id) < 15 DO
SET user_id = CONCAT(user_id, SUBSTRING('0123456789', RAND() * 10 + 1, 1));
END WHILE;
RETURN user_id;
END#
DELIMITER ;
DELIMITER #
CREATE FUNCTION GenerateUniqueUserID()
RETURNS CHAR(15)
BEGIN
DECLARE user_id CHAR(15) DEFAULT '';
REPEAT
SET user_id = GenerateRandomUserID();
UNTIL NOT UserIDExists(user_id) END REPEAT;
RETURN user_id;
END#
DELIMITER ;
I then insert a user generating its ID with this function. So far so good. The problem is when I insert another user, which generates an infinite loop. I managed to boil down the problem to yet another function, UserIDExists, which always returns TRUE (it shouldn't, obviously).
DELIMITER #
CREATE FUNCTION UserIDExists(user_id CHAR(15))
RETURNS BOOL
BEGIN
RETURN EXISTS(SELECT 1 FROM `user` WHERE `user_id` = user_id);
END#
DELIMITER ;
This last function does not do what it's supposed to, but I can't figure out why. If a single user exists with any password this will return TRUE, only if there are no users does it return FALSE. Can anyone figure out why?
Update:
I also tried this. Same result:
DELIMITER #
CREATE PROCEDURE UserIDExists(IN user_id CHAR(15), OUT user_id_exists BOOL)
BEGIN
SET user_id_exists = 0;
SELECT 1 INTO user_id_exists FROM `user` WHERE `user_id` = user_id;
END#
DELIMITER ;
Update:
Tried this as well:
DELIMITER #
CREATE PROCEDURE UserIDExists(IN user_id CHAR(15), OUT user_id_exists BOOL)
BEGIN
IF ((SELECT `user_id` FROM `user` WHERE `user_id` = user_id) != NULL) THEN
SET user_id_exists = TRUE;
ELSE
SET user_id_exists = FALSE;
END IF;
END#
DELIMITER ;
Update:
I tried a few variantes with the following:
DELIMITER #
CREATE PROCEDURE UserIDExists_2(IN user_id CHAR(15), OUT user_id_exists CHAR)
BEGIN
SELECT `user_id` FROM `user` WHERE `user_id` = user_id;
END#
DELIMITER ;
And came to the conclusion that this returns 1 when user_id is also 1 and returns nothing for any other value. This is pretty odd, because this is the only row I have on the table:
# user_id, first_name, last_name, pwd, is_confirmed
'252316605573186', 'André', 'Fratelli', NULL, '0'
This is getting on my nerves...
This works. I though that the quotes where enough to distinguish the procedure's arguments from the table's columns, but I guess I was wrong.
DELIMITER #
CREATE PROCEDURE UserIDExists(IN p_user_id CHAR(15), OUT p_user_id_exists BOOL)
BEGIN
SET p_user_id_exists = EXISTS(SELECT `user_id` FROM `user` WHERE `user_id` = p_user_id);
END#
DELIMITER ;

MySql stored functions: Not works

I have the following function:
DROP FUNCTION IF EXISTS saveTableRow;
DELIMITER $$
CREATE FUNCTION saveTableRow(adapter_id int(10), view_id int(10),name varchar(255)) RETURNS TINYINT(1)
BEGIN
DECLARE retOK TINYINT DEFAULT 0;
IF (SELECT COUNT(*) FROM `tables` WHERE `adapter_id`=adapter_id AND `view_id`=view_id AND `name`=name ) = 0 THEN
INSERT INTO `tables` (`adapter_id`,`view_id`,`name`) VALUES (adapter_id, view_id, name);
SET retOK = 1;
END IF;
RETURN retOK;
END;
$$
DELIMITER ;
When i call the function to insert a new row with
SELECT saveTableRow(3,1,'Text');
I get the result '0' and there is no new row saved.
It might be a name collision problem. The name of the column is the same with the name of you parameter. You need to change the name of your parameter that is different from the name of your column. eg,
DROP FUNCTION IF EXISTS saveTableRow;
DELIMITER $$
CREATE FUNCTION saveTableRow(
_adapter_id int(10),
_view_id int(10),
_name varchar(255))
RETURNS TINYINT(1)
BEGIN
DECLARE retOK TINYINT DEFAULT 0;
IF (SELECT COUNT(*)
FROM `tables`
WHERE `adapter_id`=_adapter_id AND
`view_id`=_view_id AND
`name`=_name ) = 0 THEN
INSERT INTO `tables` (`adapter_id`,`view_id`,`name`)
VALUES (_adapter_id, _view_id, _name);
SET retOK = 1;
END IF;
RETURN retOK;
END;
$$
DELIMITER ;
change the if as follows as try please:
IF ((SELECT COUNT(*) FROM `tables` WHERE `adapter_id`=adapter_id AND `view_id`=view_id AND `name`=name ) < 1)

Save last updated ID and date from history update made during update change trigger

I have a drivers table which has the following fields:
driver_id
first_name
last_name
nationality
dob
last_update_id
last_update_datetime
I would like to save the old data to a drivers_history table which is pretty much a mirror copy of that table and then return the id of that row and the datetime back to the drivers table in the last_update_id and last_update_datetime fields whenever an update has been made to the data.
I have the following code so far for the trigger but my knowledge of MySQL is limited coming from an ASP.Net/SQL Server background.
DROP TRIGGER IF EXISTS history_trigger $$
CREATE TRIGGER drivers_history_trigger
BEFORE UPDATE ON drivers
FOR EACH ROW
BEGIN
DECLARE _count INT;
IF OLD.first_name != NEW.first_name THEN _count = _count + 1 END IF;
IF OLD.last_name != NEW.last_name THEN _count = _count + 1 END IF;
IF OLD.nationality != NEW.nationality THEN _count = _count + 1 END IF;
IF OLD.dob != NEW.dob THEN _count = _count + 1 END IF;
IF _count > 0
THEN
INSERT INTO drivers_history (
first_name,
last_name,
nationality,
dob,
last_update_id,
last_update_datetime
)
VALUES (
NEW.first_name,
NEW.last_name,
NEW.nationality,
NEW.dob,
NULL,
NULL
);
END IF;
END;
$$
I don't know if this code works but it is where I am at so far. Please can somebody help me fill in the rest of it?
First rehash of attempted trigger code
DROP TRIGGER IF EXISTS history_trigger $$
CREATE TRIGGER drivers_history_trigger
BEFORE UPDATE ON drivers
FOR EACH ROW
BEGIN
DECLARE _count INT DEFAULT 0;
IF OLD.first_name != NEW.first_name THEN _count = _count + 1 END IF;
IF OLD.last_name != NEW.last_name THEN _count = _count + 1 END IF;
IF OLD.nationality != NEW.nationality THEN _count = _count + 1 END IF;
IF OLD.dob != NEW.dob THEN _count = _count + 1 END IF;
IF _count > 0
THEN
INSERT INTO drivers_history (
first_name,
last_name,
nationality,
dob,
last_update_id,
last_update_datetime
)
VALUES (
OLD.first_name,
OLD.last_name,
OLD.nationality,
OLD.dob,
OLD.last_update_id,
OLD.last_update_datetime
);
END IF;
END;
$$
First of all
DECLARE _count INT;
must be declare _count INT DEFAULT 0, according to docs, not specifying a default value means variable value is NULL and NULL + something_numeric is NULL.
If you say you want to save old data, your insert statement must be rewritten as:
INSERT INTO drivers_history (
first_name,
last_name,
nationality,
dob,
last_update_id,
last_update_datetime
)
VALUES (
old.first_name,
old.last_name,
old.nationality,
old.dob,
NULL,
NULL
);
I would like you to clarify what does last_update_id mean? I guess last_update_datetime is of type TIMESTAMP and will be updated automatically if you have specified in the creation table statement for that table. Also providing NULL for the values of the last two fields will prevent you to retrieve correctly, because you would be getting NULL for both values once you query back drivers_history, so to me doesn't make much sense.