Why when I do Select count(*) From table1 I receive 300 but if I do SELECT end = COUNT(*) FROM table1; returns null
Here is the fiddle example https://dbfiddle.uk/ZHzoaztV
code snippet:
CREATE TABLE table1(
start int NOT NULL,
id int PRIMARY KEY AUTO_INCREMENT,
counter int NOT NULL,
difference int NOT NULL,
end int NOT NULL
);
CREATE PROCEDURE doWhile()
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE start INT DEFAULT 120;
DECLARE counter INT DEFAULT 1;
DECLARE end INT DEFAULT 300;
WHILE (i <= end) DO
INSERT INTO table1 VALUES (start,null,counter,start+counter,end);
SET i = i+1;
SET counter = counter+1;
END WHILE;
END;
CALL doWhile();
SELECT * FROM table1;
CREATE PROCEDURE insertMore()
BEGIN
DECLARE start INT;
DECLARE counter INT DEFAULT 1;
DECLARE end INT;
SELECT end = COUNT(*) FROM table1;
SELECT start = MAX(id)+1 FROM table1;
-- SELECT COUNT(*) FROM table1;
WHILE (counter <= end) DO
INSERT INTO table1 VALUES (start,null,counter,start+counter,end);
SET counter = counter+1;
END WHILE;
END;
CALL insertMore();
SELECT * FROM table1;
I expected to return 300, so hopefully my function should do it right
You have a problem with start and end Variable
Can you try this :
CREATE PROCEDURE insertMore()
BEGIN
DECLARE start INT;
DECLARE counter INT DEFAULT 1;
DECLARE end INT;
SELECT COUNT(*) into end FROM table1;
SELECT max(id)+1 into start FROM table1;
-- SELECT COUNT(*) FROM table1;
WHILE (counter <= end) DO
INSERT INTO table1 VALUES (start,null,counter,start+counter,end);
SET counter = counter+1;
END WHILE;
END;
Try it here : https://dbfiddle.uk/X6vP3wKW
Related
I want to find the missing values percentage for each column in table name passed in missing_data_perc function parameter.
Delimiter $$
CREATE PROCEDURE missing_data_perc(IN tableName VARCHAR(30))
BEGIN
DECLARE i int default 0;
DECLARE n int default 0;
DECLARE columnName VARCHAR(30);
DECLARE perc int;
SET #tname = tableName;
SET #perc = 0;
DROP TEMPORARY TABLE IF EXISTS missing_data;
Create TEMPORARY TABLE missing_data (
data_name VARCHAR(50),
missing_data_percentage int
);
SELECT count(*) from information_schema.columns where table_name = tableName into n;
SET i=0;
while i < n Do
-- Select column_name from information_schema.columns where table_name = tableName limit i,1 into columnName;
-- Set #Q3 = CONCAT('SELECT 1-count(*)/count(columnName) from ? into ?');
-- PREPARE Stmt3 from #Q3;
-- EXECUTE Stmt3 using #tname, #perc;
-- SET perc = #perc;
SELECT 1-count(*)/count(columnName) from tableName into perc;
INSERT into missing_data VALUES (columnName, perc);
SET i = i+1;
End While;
SELECT * from missing_data;
END; $$
Delimiter ;
CALL missing_data_perc("deliveries");
Below line is giving me error:
SELECT 1-count(*)/count(columnName) from tableName into perc;
But if i change it to below statement then i works,
SELECT 1-count(*)/count(columnName) from deliveries into perc;
CREATE TABLE ZAMOWIENIA( id_zamowienia INT PRIMARY KEY NOT NULL,
id_uzytkownika INT, kwota_zamowienia DECIMAL(10,2));
INSERT INTO
ZAMOWIENIA VALUES (1,1,20), (2,4 ,5), (3,3,100), (4,1,300),
(5,2,80), (6, 1,150);
SELECT * FROM ZAMOWIENIA;
select
count(id_uzytkownika) from ZAMOWIENIA WHERE id_uzytkownika=1;
DROP
FUNCTION AccountType;
DELIMITER //
CREATE FUNCTION AccountType(
in_id_uzytkownika INT) RETURNS VARCHAR(20) DETERMINISTIC
BEGIN
DECLARE account_type VARCHAR(20);
DECLARE in_id_uzytkownika INT;
DECLARE zamowienia INT;
select count(id_uzytkownika) AS zamowienia
from ZAMOWIENIA
WHERE id_uzytkownika=in_id_uzytkownika;
select zamowienia from zamowienia;
IF zamowienia >10 THEN
SET account_type = 'BRONZE';
END IF;
IF zamowienia >30 THEN
SET account_type = 'SILVER';
END IF;
IF zamowienia >60 THEN
SET account_type = 'GOLD';
END IF;
return account_type;
END // DELIMITER ;
If you want to set a variable to the result of a SELECT query, you need to use SELECT ... INTO variable, not SELECT ... AS variable. Your function is trying to return the result of the SELECT query because it doesn't store the result into a variable.
Or you can use SET statement, which is simpler when you're just setting a single variable.
So replace the two SELECT statements with:
SET zamowienia = (SELECT COUNT(*) FROM from ZAMOWIENIA
WHERE id_uzytkownika=in_id_uzytkownika);
Also, you shouldn't have DECLARE statements for the function parameters. Remove the line
DECLARE in_id_uzytkownika INT;
I am new to MySQL Stored Procedure. I am writing a code that has a combination or cursors and CASEs.
I have a labeled loop in the cursor. Is it possible to call that labeled loop inside conditions of my CASEs
EDIT:
DROP PROCEDURE IF EXISTS ETOOLS_LATEST.SP_QueryTermsAndConditions;
COMMIT;
DELIMITER $$
CREATE PROCEDURE ETOOLS_LATEST.SP_QueryTermsAndConditions (
IN P_IN_ACCEPTED_BY VARCHAR(32),
OUT P_OUT_ACCEPTED_VERSION VARCHAR(10),
OUT P_OUT_CATEGORY VARCHAR(20),
OUT P_OUT_CURRENT_VERSION VARCHAR(10),
OUT P_OUT_FORCE_ACCEPT BOOLEAN
)
BEGIN
DECLARE noMoreRows BOOLEAN;
DECLARE loopCounter INT DEFAULT 0;
DECLARE rowCount INT DEFAULT 0;
DECLARE acceptedVersion INT(10);
DECLARE currentVersion INT(10);
DECLARE latestGeneral VARCHAR(10);
DECLARE latestBooking VARCHAR(10);
DECLARE curTnc CURSOR
FOR
SELECT a.version AS accepted_version,
a.category,
(
SELECT version
FROM apptermsandconditions c
WHERE is_latest IS True
AND c.category = a.category
) AS current_version
FROM ETOOLS_LATEST.apptermsandconditions a,
ETOOLS_LATEST.usertermsandconditions b
WHERE b.accepted_version = a.id
AND b.accepted_by = P_IN_ACCEPTED_BY;
DECLARE
CONTINUE HANDLER
FOR NOT FOUND
SET noMoreRows = TRUE;
SELECT VERSION
INTO latestGeneral
FROM ETOOLS_LATEST.AppTermsAndConditions
WHERE is_latest IS TRUE
AND CATEGORY = 'General';
SELECT VERSION
INTO latestBooking
FROM ETOOLS_LATEST.AppTermsAndConditions
WHERE is_latest IS TRUE
AND CATEGORY = 'Booking';
OPEN curTnc;
SELECT FOUND_ROWS()
INTO rowCount;
cursorLoop: LOOP
FETCH curTnc
INTO P_OUT_ACCEPTED_VERSION,
P_OUT_CATEGORY,
P_OUT_CURRENT_VERSION;
IF noMoreRows THEN
CLOSE curTnc;
LEAVE cursorLoop;
END IF;
IF P_OUT_ACCEPTED_VERSION <> P_OUT_CURRENT_VERSION THEN
SET P_OUT_FORCE_ACCEPT = 1;
ELSE
SET P_OUT_FORCE_ACCEPT = 0;
END IF;
SELECT P_OUT_ACCEPTED_VERSION,
P_OUT_CATEGORY,
P_OUT_CURRENT_VERSION,
P_OUT_FORCE_ACCEPT;
SET loopCounter = loopCounter + 1;
END LOOP cursorLoop;
CASE rowCount
WHEN 0
THEN
SELECT null, 'General', latestGeneral, 1;
SELECT null, 'Booking', latestBooking, 1;
WHEN 1
THEN
CASE P_OUT_CATEGORY
WHEN 'General'
THEN
SELECT null, 'Booking', latestBooking, 1;
WHEN 'Booking'
THEN
SELECT null, 'General', latestGeneral, 1;
END CASE;
WHEN 2
THEN
SELECT null;
END CASE;
END $$
DELIMITER ;
CALL SP_QueryTermsAndConditions('333333', #P_OUT_ACCEPTED_VERSION, #P_OUT_CATEGORY, #P_OUT_CURRENT_VERSION, #P_OUT_FORCE_ACCEPT);
in my store procedure i want to have simple function to return value. i want to have this Sql command to function ( thats duplicate action in my procedure):
/*************************************************/
CREATE FUNCTION getDelay( INT id(11) )
SET #v_is_new := (SELECT COUNT(id) from `tsms_entry_exit` WHERE DATE_FORMAT(`datetime_in`, '%Y-%m-%d') = CURDATE() );
IF #v_is_new IS NULL THEN
SET #v_delay := SEC_TO_TIME (TIME_TO_SEC(_datetime_in) - TIME_TO_SEC(#v_user_start_time)) ;
ELSE
SET #v_delay :=0;
END IF;
RETURN #v_delay;
/*************************************************/
i want to have that function into below store procedure how to have this action??
CREATE DEFINER=`root`#`localhost` PROCEDURE `tsmsp_post_entry_exit`(IN `_id` INT(11), IN `_user_id` INT(5), IN `_datetime_in` DATETIME, IN `_datetime_out` DATETIME)
NO SQL
BEGIN
DECLARE v_user_start_time INT UNSIGNED;
DECLARE v_delay INT(11);
DECLARE v_pyear INT UNSIGNED;
DECLARE v_mounth INT UNSIGNED;
SET #v_pyear = pyear ( _datetime_in ) ;
SET #v_mounth = pmonth( _datetime_in );
SET #v_user_start_time := (SELECT `start_time` FROM `tsms_range_time` WHERE `user_id` = _user_id);
IF _id IS NULL THEN
/* Check for first record today for calculate Delay*/
SET #v_is_new := (SELECT COUNT(id) from `tsms_entry_exit` WHERE DATE_FORMAT(`datetime_in`, '%Y-%m-%d') = CURDATE() );
/* calculate USER delay */
IF #v_is_new IS NULL THEN
SET #v_delay := SEC_TO_TIME (TIME_TO_SEC(_datetime_in) - TIME_TO_SEC(#v_user_start_time)) ;
ELSE
SET #v_delay :=0;
END IF;
INSERT INTO `tsms_entry_exit`
(
`user_id`,
`datetime_in`,
`datetime_out`,
`delay`,
`period`
)
VALUES
(
_user_id,
_datetime_in,
_datetime_out,
#v_delay,
CONCAT(#v_pyear, #v_mounth)
);
SELECT ROW_COUNT() AS 'Affected rows';
ELSE
BEGIN
/* Check for first record today for calculate Delay*/
SET #v_is_new := (SELECT COUNT(id) from `tsms_entry_exit` WHERE DATE_FORMAT(`datetime_in`, '%Y-%m-%d') = CURDATE() );
/* calculate USER delay */
IF #v_is_new IS NULL THEN
SET #v_delay := SEC_TO_TIME (TIME_TO_SEC(_datetime_in) - TIME_TO_SEC(#v_user_start_time)) ;
ELSE
SET #v_delay :=0;
END IF;
UPDATE `tsms_entry_exit` SET
`user_id`= _user_id,
`datetime_in` = _datetime_in,
`datetime_out`=_datetime_out,
`delay`=_delay,
`period`=_period
WHERE `id` = _id;
SELECT ROW_COUNT() AS 'Affected Update rows';
END;
END IF;
END
You can't define the function inside procedure but you can call the function though. A simplest example would be like below.
Create your function
DELIMITER $$
CREATE FUNCTION getDelay(id int)
returns int
begin
SET #v_is_new := (SELECT COUNT(id) from `tsms_entry_exit`
WHERE DATE_FORMAT(`datetime_in`, '%Y-%m-%d') = CURDATE() );
IF(#v_is_new IS NULL) THEN
SET #v_delay := SEC_TO_TIME (TIME_TO_SEC(_datetime_in) - TIME_TO_SEC(#v_user_start_time)) ;
ELSE
SET #v_delay :=0;
END IF;
RETURN #v_delay;
end $$
DELIMITER ;
Then call the above defined function in your procedure
DELIMITER $$
CREATE PROCEDURE `tsmsp_post_entry_exit`(IN `_id` INT)
BEGIN
DECLARE v_delay INT;
IF _id IS NULL
THEN
select #v_delay := getDelay(_id); <-- Calling Here
END IF;
END $$
DELIMITER ;
I have a table that stores some comma separated strings. Is there a way to write a sql to
return me a separate rows for each token string obtained by splitting across commas.
You can simply write and call a stored procedure
DELIMITER $$
DROP PROCEDURE IF EXISTS explode_table $$
CREATE PROCEDURE explode_table(bound VARCHAR(255))
BEGIN
DECLARE id INT DEFAULT 0;
DECLARE value TEXT;
DECLARE occurance INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE splitted_value INT;
DECLARE done INT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT table1.id, table1.value
FROM table1
WHERE table1.value != '';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
DROP TEMPORARY TABLE IF EXISTS table2;
CREATE TEMPORARY TABLE table2(
`id` INT NOT NULL,
`value` VARCHAR(255) NOT NULL
) ENGINE=Memory;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO id, value;
IF done THEN
LEAVE read_loop;
END IF;
SET occurance = (SELECT LENGTH(value)
- LENGTH(REPLACE(value, bound, ''))
+1);
SET i=1;
WHILE i <= occurance DO
SET splitted_value =
(SELECT REPLACE(SUBSTRING(SUBSTRING_INDEX(value, bound, i),
LENGTH(SUBSTRING_INDEX(value, bound, i - 1)) + 1), ',', ''));
INSERT INTO table2 VALUES (id, splitted_value);
SET i = i + 1;
END WHILE;
END LOOP;
SELECT * FROM table2;
CLOSE cur1;
END; $$
-------------------
CALL explode_table(',');