MySql Procedure for randomly populating rows only populates one row - mysql

I have a procedure that populates randomly records in a table.
But when i execute that procedure, the procedure inserts only one row.
CAN ANYONE HELP!
create procedure aa
( #row INT
)
as
begin
declare #numint as int
declare #string as VARCHAR(10)
declare #length as INT
declare #code as INT
declare #oid as uniqueidentifier
set #numint =0;
WHILE #numint <= #row
BEGIN
SET #numint = #numint + 1;
set #oid = newid();
SET #length = ROUND(10*RAND(),0);
SET #string = '';
WHILE #length > 0 BEGIN
SET #length = #length-1;
SET #code = ROUND(10*RAND(),0) - 1;
IF #code BETWEEN 1 AND 26
SET #string = #string + CHAR(ASCII('a')+#code-1);
ELSE
SET #string = #string + ' ';
END
end
-- Ready for the record
SET NOCOUNT ON;
INSERT INTO test_table VALUES (
#oid,
#numint,
ROUND(2000000*RAND()-1000000,2),
CONVERT(DATETIME, ROUND(50000*RAND()-10000,2)),
#string
)
END
exec procedure '10'

Your insert statement is outside of the loop. Move it up to be inside the first loop and you should get the correct number of rows.

Related

mySQL procedure does not commit on commit statement

This is my code:
BEGIN
DECLARE _cnt INT;
DECLARE i INT DEFAULT 0 ;
DECLARE j INT DEFAULT 0 ;
DECLARE _FIPSAPNCombo VARCHAR(30) DEFAULT '00000';
DECLARE _prv_FIPSAPNCombo VARCHAR(30) DEFAULT '00000';
DECLARE _Rollyear INT DEFAULT 2000;
DECLARE _first_Rollyear INT DEFAULT 2000;
DECLARE eof boolean default FALSE;
DECLARE _AvTotal INT;
DECLARE _prv_AvTotal INT default 0;
DECLARE _YOY_PCT INT;
DECLARE _YOY_USD INT;
DECLARE _in_pct INT;
DECLARE _in_usd INT;
DECLARE _last INT;
DECLARE _id INT;
DECLARE _idx INT;
DECLARE _prv_id INT;
DECLARE get_FIPSAPNCombo CURSOR
FOR
SELECT 0, '0', 2000, 1
UNION
SELECT id, FIPSAPNCombo, rollyear, AvTotal
FROM AvHistory_06037 AS h
WHERE substr(h.FIPSAPNCombo,1,8) = _in_FIPSAPNCombo_8
AND h.AvTotal > 0
ORDER BY 2, 3
;
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET eof = TRUE;
SELECT YOY_PCT, YOY_USD INTO _in_pct, _in_usd FROM AlertSearches WHERE id = _in_AlertSearchesID;
START TRANSACTION;
OPEN get_FIPSAPNCombo;
doit: LOOP
fetch get_FIPSAPNCombo INTO _id, _FIPSAPNCombo, _Rollyear, _AvTotal;
SET _YOY_USD = _AvTotal - _prv_AvTotal;
SET _YOY_PCT = ROUND((((_AvTotal - _prv_AvTotal) / _prv_AvTotal) * 100),0);
IF eof = TRUE THEN
LEAVE doit;
END IF;
IF _FIPSAPNCombo != _prv_FIPSAPNCombo THEN SET _first_Rollyear = _Rollyear; ELSE SET _first_Rollyear = '2000'; END IF;
IF _YOY_PCT >= _in_pct AND _YOY_USD >= _in_usd and _Rollyear != _first_Rollyear THEN
BEGIN
DELETE FROM AvHistoryAlerts WHERE FIPSAPNCombo = _FIPSAPNCombo AND AlertSearchesID = _in_AlertSearchesID;
INSERT INTO AvHistoryAlerts VALUES (_id, _FIPSAPNCombo, '06037', _Rollyear, _AvTotal, _YOY_PCT, _YOY_USD, _prv_id, _prv_AvTotal, _in_AlertSearchesID);
UPDATE AvHistory SET CausalTransfer = NULL WHERE FIPSAPNCombo = _FIPSAPNCombo;
UPDATE AvHistory SET CausalTransfer = 'Green' WHERE id = _id;
SET i = i + 1;
IF mod(i,1000) = 0 THEN insert into error_log VALUES (concat(_in_FIPSAPNCombo_8, ' > calc_YOY_increase i = ', i, ' ',now())); COMMIT; START TRANSACTION; END IF;
END;
END IF;
SET _prv_FIPSAPNCombo = _FIPSAPNCombo;
SET _prv_AvTotal = _AvTotal;
SET _prv_id = _id;
SET eof = FALSE;
END LOOP;
COMMIT;
CLOSE get_FIPSAPNCombo;
END
I thought that the procedure would commit every 1000 records processed and that this would be reflected in the error_log table in real time.
But, the data is only available after the procedure finishes completely and then all the records show up all at once in the error_log table.
That, by itself, is not the issue: what I am concerned about is the the procedure seems to dwell on "waiting for handler commit" for a long time at the end of the procedure.
So, I'm not sure what's going on: is it storing everything in memory or in a temp table or file and then needs a lot if time for cleanup?
I thought that a commit would clear all that... but it does not seem to commit until the end of the whole procedure
Any ideas?

How can i concat the values in MySql?

Please find the below code, The below code is sql server code[Stored Procedure] i am converting sql to mysql in this link mysql and below is the sql SP
USE databasename
GO
ALTER PROCEDURE GetSbsberIDbyDept
#P_DepartmentIds varchar(max),
#OP_ID varchar(max) output
AS
BEGIN
Declare #Position int
Declare #length int
Declare #value varchar(8000)
Declare #SubscribrIDs varchar(max)
Declare #FinalSubscriberids varchar(max) = ''
SET #Position = 0
SET #length = 0
select #P_DepartmentIds
WHILE CHARINDEX(',', #P_DepartmentIds, #Position+1)>0
BEGIN
set #Length = CHARINDEX(',', #P_DepartmentIds, #Position+1) - #Position
set #value = SUBSTRING(#P_DepartmentIds, #Position, #length)
select #SubscribrIDs = STUFF((SELECT ', ' + cast(SubscriberId as varchar(max)) from SbsberDetails
where Deptid = #value and ParentId is null order by SubscriberId asc FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,2,'')
if(#SubscribrIDs is not null)
begin
set #FinalSubscriberids += cast(#SubscribrIDs as varchar(max)) + ',';
end
set #Position = CHARINDEX(',', #P_DepartmentIds, #Position + #length) +1
END
SET #OP_ID = #FinalSubscriberids
END
And i converted to MySql but i am getting the error in STUFF statement like STUFF is not valid input at this position, below is the Mysql code
USE databasename
DELIMITER //
CREATE PROCEDURE GetSbsberIDbyDept(
p_P_DepartmentIds longtext,
p_OP_ID out longtext )
BEGIN
Declare v_Position int;
Declare v_length int;
Declare v_value varchar(8000);
Declare v_SubscribrIDs longtext;
Declare v_FinalSubscriberids longtext Default '';
SET v_Position = 0;
SET v_length = 0;
select p_P_DepartmentIds
WHILE; CHARINDEX(',', p_P_DepartmentIds, v_Position+1)>0
BEGIN
set v_length = CHARINDEX(',', p_P_DepartmentIds, v_Position+1) - v_Position;
set v_value = SUBSTRING(p_P_DepartmentIds, v_Position, v_length);
set v_SubscribrIDs = STUFF((SELECT Concat(', ' , cast(SubscriberId as longtext)) from SbsberDetails
where Deptid = v_value and ParentId is null order by SubscriberId asc FOR XML; PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,2,'')
if(v_SubscribrIDs is not null)
then
set v_FinalSubscriberids += concat(cast(v_SubscribrIDs as longtext) , ',');
end if;
set v_Position = CHARINDEX(',', p_P_DepartmentIds, v_Position + v_length) +1;
END;
SET p_OP_ID = v_FinalSubscriberids;
END;
//
DELIMITER ;
How do i convert the above sql code to MySql?
STUFF is SQL server function so it's thrown error in mysql, The thing that i got your are trying to row concat but in mysql there is funtion name GROUP_CONCAT for group cancating ,so you can use it instead of stuff

Stored Procedures IN mySQL

I am trying to convert hours to minutes using Stored Procedures in MySQL. For example,I am getting the output as 3 hour 15 minutes . I need to convert it as 195 minutes. I tried using multiple cases but nothing worked out for me.. Can you please help me if you have any code to solve this???
You could use Function for this purpose.
DELIMITER $$
CREATE FUNCTION `toMinutes`
(
hour INT,
minute INT
)
RETURNS INTEGER
BEGIN
DECLARE result INT;
SET result = (hour * 60) + minute;
RETURN result;
END$$
DELIMITER ;
Call the function:
SELECT toMinutes(1,1);
I worked on the requirement and able to create a function successfully as follows!!!
/****** Object: UserDefinedFunction [dbo].[BUSINESS_DURATION_MINTS_FN] Script Date: 10/17/2017 12:22:12 PM ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[BUSINESS_DURATION_MINTS_FN]
(#string varchar(100) )
RETURNS INT
AS
BEGIN
DECLARE #total_mints INT
DECLARE #hours INT
DECLARE #Mints INT
IF #string IS NOT NULL
BEGIN
SET #string = REPLACE(UPPER(#string),'HOURS','HOUR')
SET #string = REPLACE(UPPER(#string),'MINUTES','MINUTE')
IF ((CHARINDEX(UPPER('HOUR'),UPPER(#string))!=0) AND (CHARINDEX(UPPER('MINUTE'),UPPER(#string))!= 0))
BEGIN
SET #hours = CONVERT(INT,SUBSTRING(#string,1, (CHARINDEX(UPPER('HOUR'), UPPER(#string))-2)))
SET #Mints = CONVERT(INT,SUBSTRING(#string,(CHARINDEX(UPPER('HOUR'),UPPER(#string))+4),(CHARINDEX(UPPER('MINUTE'),UPPER(#string))-(CHARINDEX(UPPER('HOUR'), UPPER(#string))+5))))
END
IF ((CHARINDEX(UPPER('HOUR'),UPPER(#string))=0) AND (CHARINDEX(UPPER('MINUTE'),UPPER(#string))!= 0))
BEGIN
SET #hours = 0
SET #Mints = CONVERT(INT,SUBSTRING(#string,1, (CHARINDEX(UPPER('MINUTE'), UPPER(#string))-2)))
END
IF ((CHARINDEX(UPPER('HOUR'),UPPER(#string))!=0) AND (CHARINDEX(UPPER('MINUTE'),UPPER(#string))=0))
BEGIN
SET #hours = CONVERT(INT,SUBSTRING(#string,1, (CHARINDEX(UPPER('HOUR'), UPPER(#string))-2)))
SET #Mints = 0
END
IF ((CHARINDEX(UPPER('HOUR'),UPPER(#string))= 0) AND (CHARINDEX(UPPER('MINUTE'),UPPER(#string))=0))
BEGIN
SET #hours = 0
SET #Mints = 0
END
SET #total_mints = #hours*60 + #Mints
END
IF #string IS NULL
BEGIN
SET #total_mints = NULL
END
RETURN #total_mints
END
GO

Insert n number of rows into table when input string contains n number of fields in mysql

I do have a requirement like when two inputs are passed as input to stored proc, inserting into another table need to happen and the number of rows will depend on number of fields passed in input.
I have tried to create a stored proc but its only inserting taking field length as 1
BEGIN
Declare valu varchar(200);
Declare valu2 varchar(200);
Declare fwo varchar(200);
Declare fwo2 varchar(200);
declare len int;
Declare sl int;
Declare valu3 varchar(255);
Declare jval varchar(255);
set #fwo = (select replace(pinput1,',', ''));
set #fwo2 = (select replace(pinput2,',', ''));
-- select #fwo;
set #len = (select length(#fwo));
-- select #fwo,#len;
set #sl = 1;
if #len >0 then
increment: repeat
set #valu = SUBSTRING(#fwo, #sl , 1);
set #valu2 = SUBSTRING(#fwo2, #sl , 1);
set #jval = JSON_OBJECT('id',#valu2,'policy',#valu);
INSERT INTO `Example`(`Column1`,`Column2`) values(#valu2,#jval);
set #sl = #sl+1;
UNTIL #sl > #len END repeat increment ;
END if ;
END$$
DELIMITER ;
When the input are 1,2,3 and a,b,c the insertion is happening correctly, but when we pass 11,12,13 and ab,cd,ef the insertion is happening likethe above condition inputs.The same repetes when the lenght increases more than 1.
Can someone suggestion me to solve this issue

Compare String function in mysql by words

I am trying to create a search function in mysql. In order to make the search result more reliability i need to compare two string by words. Inputs are 2 strings and output is number word two strings match. In MySql i did as below.
CREATE DEFINER=`root`#`localhost` FUNCTION `CompareStrings`(str1 VARCHAR(255),str2 VARCHAR(255)) RETURNS double
BEGIN
DECLARE cur_position INT DEFAULT 1 ;
DECLARE remainder TEXT;
DECLARE cur_string VARCHAR(50);
DECLARE delimiter_length TINYINT UNSIGNED;
DECLARE numberMatch INT;
DECLARE total INT;
DECLARE result DOUBLE DEFAULT 0;
DECLARE delim VARCHAR(10);
DECLARE string2 VARCHAR(255);
SET delim = ' ';
DROP TEMPORARY TABLE IF EXISTS SplitString1;
CREATE TEMPORARY TABLE SplitString1 (
SplitString1ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT ,
val VARCHAR(50) NOT NULL
) ENGINE=MyISAM;
DROP TEMPORARY TABLE IF EXISTS SplitString2;
CREATE TEMPORARY TABLE SplitString2 (
SplitString1ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT ,
val VARCHAR(50) NOT NULL
) ENGINE=MyISAM;
SET remainder = str1;
SET delimiter_length = CHAR_LENGTH(delim);
WHILE CHAR_LENGTH(remainder) > 0 AND cur_position > 0 DO
SET cur_position = INSTR(remainder, delim);
IF cur_position = 0 THEN
SET cur_string = remainder;
ELSE
SET cur_string = LEFT(remainder, cur_position - 1);
END IF;
IF TRIM(cur_string) != '' THEN
INSERT INTO SplitString1(val) VALUES (cur_string);
END IF;
SET remainder = SUBSTRING(remainder, cur_position + delimiter_length);
END WHILE;
SET remainder = str2;
SET cur_position = 1;
WHILE CHAR_LENGTH(remainder) > 0 AND cur_position > 0 DO
SET cur_position = INSTR(remainder, delim);
IF cur_position = 0 THEN
SET cur_string = remainder;
ELSE
SET cur_string = LEFT(remainder, cur_position - 1);
END IF;
IF TRIM(cur_string) != '' THEN
INSERT INTO SplitString2(val) VALUES (cur_string);
END IF;
SET remainder = SUBSTRING(remainder, cur_position + delimiter_length);
END WHILE;
SELECT count(*) INTO numberMatch
FROM SplitString1 s1 JOIN SplitString2 s2 ON s1.val = s2.val;
RETURN result;
END
The idea is create two temporary table store each word and then compare these 2 tables. The result is good but the performace is awful. Anybody has better idea, please give me an advice.
Many thanks!
I don't think this will work as stated.
The logic is sound but you have not assigned any value to your result variable. Hence this function will always return 0. Replace:
RETURN result;
with
RETURN numberMatch;
Also replace:
CREATE DEFINER=`root`#`localhost` FUNCTION `CompareStrings`(str1 VARCHAR(255),str2 VARCHAR(255)) RETURNS double
with
CREATE DEFINER=`root`#`localhost` FUNCTION `CompareStrings`(str1 VARCHAR(255),str2 VARCHAR(255)) RETURNS double READS SQL DATA
As far as efficiency goes it looks pretty efficient. When you say 'performance is awful' - what constitutes 'awful'? Have you got any benchmark figures e.g. x calls took y millis?