MySql stored functions: Not works - mysql

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)

Related

Procedure Slow update records

How to improve the procedure to perform faster?
I have 3 procedures, the first searches the balance before the second updates the balance and the third I use to do the processing where I call the two previous procedures.
In short, when I insert a table record a timer in the service redo the balance processing by calling the procedure PROC_PROCESSAR_SALDO.
DROP PROCEDURE IF EXISTS `PROC_SALDO_ANTERIOR`;
DELIMITER $$
CREATE PROCEDURE `PROC_SALDO_ANTERIOR` (
IN codigo_Empresa_par INT,
IN codigo_Filial_par INT,
IN codigo_Conta_par INT,
IN sequencia_par BIGINT(20),
IN data_Hora_par DATETIME,
OUT sequencia_ret BIGINT(20),
OUT data_Hora_ret DATETIME,
OUT saldo_Atual_ret DECIMAL(20, 2)
)
BEGIN
SELECT SEQUENCIA, DATAHORA, SALDO_ATUAL INTO sequencia_ret, data_Hora_ret, saldo_Atual_ret
FROM CONTAS_CORRENTES
WHERE CODIGO_EMPRESA = codigo_Empresa_par AND
CODIGO_FILIAL = codigo_Filial_par AND
CODIGO_CONTA = codigo_Conta_par AND
((DATAHORA =data_Hora_par AND SEQUENCIA < sequencia_par) OR (DATAHORA < data_Hora_par))
ORDER BY DATAHORA DESC, SEQUENCIA DESC LIMIT 1;
if sequencia_ret IS NULL THEN
SET sequencia_ret := 0;
SET data_Hora_ret := '0001/01/01 12:00:00';
SET saldo_Atual_ret := 0;
END IF;
END;
DELIMITER ;
DROP PROCEDURE IF EXISTS `PROC_ATUALIZAR_SALDO`;
DELIMITER $$
CREATE PROCEDURE `PROC_ATUALIZAR_SALDO` (
IN codigo_Empresa_par INT,
IN codigo_Filial_par INT,
IN codigo_Conta_par INT,
IN sequencia_par BIGINT(20),
IN data_Hora_par DATETIME,
IN saldo_Atual_par DECIMAL(20,2)
)
BEGIN
DECLARE SEQUENCIA_NEW BIGINT(20) DEFAULT 0;
DECLARE DEBITO_NEW DECIMAL(20,2) DEFAULT 0;
DECLARE CREDITO_NEW DECIMAL(20,2) DEFAULT 0;
DECLARE SALDO_ANTERIOR DECIMAL(20,2) DEFAULT 0;
DECLARE done INT DEFAULT FALSE;
DECLARE cur CURSOR FOR SELECT A.SEQUENCIA, A.DEBITO, A.CREDITO
FROM CONTAS_CORRENTES A
WHERE A.CODIGO_EMPRESA = codigo_Empresa_par AND
A.CODIGO_FILIAL = codigo_Filial_par AND
A.CODIGO_CONTA = codigo_Conta_par AND
((A.DATAHORA = data_Hora_par AND
A.SEQUENCIA > sequencia_par) OR
(A.DATAHORA > data_Hora_par))
ORDER BY A.DATAHORA ASC,
A.SEQUENCIA ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
START TRANSACTION;
SET SALDO_ANTERIOR := saldo_Atual_par;
OPEN cur;
ins_loop: LOOP
FETCH cur INTO SEQUENCIA_NEW, DEBITO_NEW, CREDITO_NEW;
IF done THEN
LEAVE ins_loop;
END IF;
SET SALDO_ANTERIOR := SALDO_ANTERIOR - DEBITO_NEW + CREDITO_NEW;
UPDATE CONTAS_CORRENTES SET SALDO_ATUAL = SALDO_ANTERIOR
WHERE CODIGO_EMPRESA = codigo_Empresa_par AND
CODIGO_FILIAL = codigo_Filial_par AND
CODIGO_CONTA = codigo_Conta_par AND
SEQUENCIA = SEQUENCIA_NEW;
END LOOP;
CLOSE cur;
COMMIT;
END $$
DELIMITER ;
DROP PROCEDURE IF EXISTS `PROC_PROCESSAR_SALDO`;
DELIMITER $$
CREATE PROCEDURE `PROC_PROCESSAR_SALDO` (
IN codigo_Empresa_new INT,
IN codigo_Filial_new INT,
IN codigo_Conta_new INT,
IN sequencia_new BIGINT(20),
IN data_Hora_new DATETIME
)
BEGIN
CALL PROC_SALDO_ANTERIOR(codigo_Empresa_new, codigo_Filial_new, codigo_Conta_new, sequencia_new,
data_Hora_new, #sequencia_ret, #data_Hora_ret, #saldo_Atual_ret);
CALL PROC_ATUALIZAR_SALDO(codigo_Empresa_new, codigo_Filial_new, codigo_Conta_new, #sequencia_ret,
#data_Hora_ret, #saldo_Atual_ret);
END $$
DELIMITER ;
CALL PROC_PROCESSAR_SALDO(#CODIGO_EMPRESA, #CODIGO_FILIAL, #CODIGO_CONTA, #SEQUENCIA, #DATAHORA);
You have to check what makes the queries slow. You basically have two things to check:
Do the individual queries use indexes?
Does the cursor loop produce so many rows that (mabye an slightly unoptimized) query in the loop adds up leading to the slow performance
Check the individual queries with EXPLAIN for index use. You can also add select now() after in each query and execute the procedure and you should see which part consumes the time.

Create mysql function failed in phpmyadmin

When I try to make this function it always failed.
DELIMITER $$
CREATE FUNCTION `f_hadir`(ID INT)
RETURNS INT
BEGIN
DECLARE TMP INT;
SELECT COUNT(ID_presensi_siswa) into TMP
FROM presensi_siswa
WHERE keterangan='Hadir' AND id_siswa=id LIMIT 1;
RETURN TMP;
END$$
DELIMITER ;
i had similiar code but and it successfully created.
DROP FUNCTION IF EXISTS `CategoriesToString`;
DELIMITER ;;
CREATE FUNCTION `CategoriesToString`(TID int) RETURNS varchar(500) CHARSET utf8
BEGIN
DECLARE result varchar(500);
SELECT group_concat(Category.Name) INTO result FROM Category
WHERE ID IN (SELECT CategoryID FROM TopicHasCategory WHERE TopicID = TID) LIMIT 1;
RETURN result;
END;;
DELIMITER ;
Anyone have idea?

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 ;

Call procedure inside trigger in mysql

I want to update counter table when user table is modofied.
I have created a trigger where i will cal this procedure.
But this procudeure is not creating.
Please tell me what error in this procedure.
CREATE PROCEDURE barproc(IN id int,IN val int)
BEGIN
DECLARE #total_products int;
set #total_products=(SELECT COUNT(*)
FROM user where a=id and status='active')
if(#total_products>0)
update counter
set b=val
WHERE a = id and status='active';
END if;
Try
DELIMITER $$
CREATE PROCEDURE barproc(IN id INT, IN val INT)
BEGIN
IF (SELECT COUNT(*)
FROM `user`
WHERE a = id AND `status` = 'active') THEN
UPDATE counter
SET b = val
WHERE a = id AND `status` = 'active';
END IF;
END$$
DELIMITER ;