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
This procedure does not return 2, it always returns 1. How to return 1 when insert happens, and return 2 when an update happens?
It is perfectly insert and update but return value always 1.
CREATE PROCEDURE [dbo].[sp_SaveEmployeeDetails]
#employeeID int
,#first_name varchar(255)
,#middle_name varchar(255)
,#last_name varchar(255)
,#gender varchar(255)
,#date_of_birth date
,#EntryBy varchar(255)
--,#ActionStatus int = NULL OUTPUT
AS
BEGIN
SET NOCOUNT OFF;
DECLARE #ActionStatus int;
IF NOT EXISTS(Select * From employees
Where employeeID =#employeeID)
BEGIN
INSERT INTO [dbo].[employees] ([first_name], [middle_name], [last_name], [gender], [date_of_birth], [EntryBy], [EntryDate])
VALUES (#first_name, #middle_name, #last_name, #gender, #date_of_birth, #EntryBy, getdate())
SET #ActionStatus = 1;
END
ELSE
BEGIN
UPDATE employees
SET [first_name] = #first_name,
[middle_name] = #middle_name,
[last_name] = #last_name,
[gender] = #gender,
[date_of_birth] = #date_of_birth,
[EntryBy] = #EntryBy,
[EntryDate] = getdate()
WHERE
employeeID = #employeeID
SET #ActionStatus = 2;
END
RETURN #ActionStatus;
--also try SELECT #ActionStatus;
END
The value you return here
RETURN #ActionStatus;
...might be set to a variable directly, its the procedure's "own" return value. Look at this example:
CREATE PROCEDURE dbo.TestReturn(#IntValue INT)
AS
BEGIN
IF #IntValue=0
RETURN 0;
ELSE
RETURN 1;
END
GO
DECLARE #RetVal INT;
EXEC #RetVal = dbo.TestReturn -1;
SELECT #RetVal;
EXEC #RetVal = dbo.TestReturn 0;
SELECT #RetVal;
EXEC #RetVal = dbo.TestReturn 1;
SELECT #RetVal;
GO
DROP PROCEDURE dbo.TestReturn;
It comes back with 1-0-1 as expected.
But this return value is bound to INT and is meant to reflect execution states (like error codes, success level...) In your case this seems to be the case...
If you think about output of any other data use OUTPUT parameters.
CREATE PROCEDURE dbo.TestReturn(#IntValue INT, #TestPrm VARCHAR(100) OUTPUT)
AS
BEGIN
IF #IntValue=0
BEGIN
SET #TestPrm='Value was 0'
RETURN 0;
END
ELSE
BEGIN
SET #TestPrm='Value was something else';
RETURN 1;
END
END
GO
DECLARE #RetVal INT;
DECLARE #RetVarchar VARCHAR(100);
EXEC #RetVal = dbo.TestReturn -1,#RetVarchar OUTPUT;
SELECT #RetVal,#RetVarchar;
EXEC #RetVal = dbo.TestReturn 0,#RetVarchar OUTPUT;
SELECT #RetVal,#RetVarchar;
EXEC #RetVal = dbo.TestReturn 1,#RetVarchar OUTPUT;
SELECT #RetVal,#RetVarchar;
GO
DROP PROCEDURE dbo.TestReturn;
I created the following function to input records by parsing a string:
DROP FUNCTION IF EXISTS RowPerRow ;
DELIMITER $$
CREATE FUNCTION RowPerRow()
RETURNS VARCHAR(300)
BEGIN
DECLARE n INT DEFAULT 0 ;
DECLARE m INT DEFAULT 0 ;
DECLARE i INT DEFAULT 0 ;
DECLARE j INT DEFAULT 0 ;
SELECT count(*) FROM Temp0 INTO n ;
WHILE i < n DO
SELECT words INTO m FROM Temp0 LIMIT i, 1 ;
SET j = 1 ;
WHILE j <= m DO
INSERT INTO Temp1 SELECT words,id,api,basin,play,drilltype,tradeflag,score,cnf,fracdate,
fracdateend,state,county,operator,wellname,prodtype,latitude,
longitude,datum,depth,water,nonwater,surfactant,tradename,TRIM(Split_Str(tradename, ',', j)) AS tradename_c,
supplier,purpose,ingredients,cas,additive,fluid
FROM Temp0 LIMIT i,1 ;
SET j = j + 1 ;
END WHILE ;
SET i = i + 1 ;
END WHILE ;
RETURN '' ;
END ;
$$
The function gets progressively slower as the number of records increase.
If the question is "What is an example of an alternative way to do this same RBAR (row-by-agonizing-row) processing but which doesn't get progressively slower", I can give an example of what that would look like.
If there's an upper bound (maximum value) for words, this same result can be accomplished in a single statement:
INSERT INTO Temp1
( words, id, api, basin, play, drilltype, tradeflag ,score ,cnf, fracdate, fracdateend, state, county, operator, wellname, prodtype, latitude, longitude, datum, depth, water, nonwater, surfactant, tradename, supplier, purpose, ingredients, cas, additive, fluid
, tradename_c )
SELECT t.words,t.id,t.api,t.basin,t.play,t.drilltype,t.tradeflag,t.score,t.cnf,t.fracdate,t.fracdateend,t.state,t.county,t.operator,t.wellname,t.prodtype,t.latitude,t.longitude,t.datum,t.depth,t.water,t.nonwater,t.surfactant,t.tradename,t.supplier,t.purpose,t.ingredients,t.cas,t.additive,t.fluid
, TRIM(Split_Str(t.tradename, ',', n.i)) AS tradename_c
FROM Temp0 t
JOIN (SELECT 1 AS i UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20) n
ON n.i <= t.words
But here is an example of a procedure that does the equivalent of the original procedure, except that it uses cursor loop instead of repeatedly re-querying the Temp0 table. Note that the datatypes of the variables (which accept the values from the row returned by fetch) should match or be compatible with the datatype of the corresponding expression in the SELECT list. Here I've declared them all as VARCHAR(100) as a placeholder, these will need to be changed to match the columns from the Temp0 table.
DELIMITER $$
CREATE FUNCTION RowPerRow_alt()
RETURNS VARCHAR(300)
BEGIN
-- variables for cursor fetch
-- the datatype of each variable should match the datatype
-- of the expression in SELECT list of the query
DECLARE v_words INT;
DECLARE v_id VARCHAR(100);
DECLARE v_api VARCHAR(100);
DECLARE v_basin VARCHAR(100);
DECLARE v_play VARCHAR(100);
DECLARE v_drilltype VARCHAR(100);
DECLARE v_tradeflag VARCHAR(100);
DECLARE v_score VARCHAR(100);
DECLARE v_cnf VARCHAR(100);
DECLARE v_fracdate VARCHAR(100);
DECLARE v_fracdateend VARCHAR(100);
DECLARE v_state VARCHAR(100);
DECLARE v_county VARCHAR(100);
DECLARE v_operator VARCHAR(100);
DECLARE v_wellname VARCHAR(100);
DECLARE v_prodtype VARCHAR(100);
DECLARE v_latitude VARCHAR(100);
DECLARE v_longitude VARCHAR(100);
DECLARE v_datum VARCHAR(100);
DECLARE v_depth VARCHAR(100);
DECLARE v_water VARCHAR(100);
DECLARE v_nonwater VARCHAR(100);
DECLARE v_surfactant VARCHAR(100);
DECLARE v_tradename VARCHAR(100);
DECLARE v_supplier VARCHAR(100);
DECLARE v_purpose VARCHAR(100);
DECLARE v_ingredients VARCHAR(100);
DECLARE v_cas VARCHAR(100);
DECLARE v_additive VARCHAR(100);
DECLARE v_fluid VARCHAR(100);
DECLARE j INT DEFAULT 0 ;
DECLARE v_tradename_c VARCHAR(100);
DECLARE done TINYINT(1) DEFAULT 0;
-- cursor for Temp0
DECLARE csr CURSOR FOR
SELECT words,id,api,basin,play,drilltype,tradeflag,score,cnf,fracdate,
fracdateend,state,county,operator,wellname,prodtype,latitude,
longitude,datum,depth,water,nonwater,surfactant,tradename,
supplier,purpose,ingredients,cas,additive,fluid
FROM Temp0;
-- setup NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN csr;
rowloop: LOOP
FETCH csr INTO v_words,v_id,v_api,v_basin,v_play,v_drilltype,v_tradeflag,v_score,v_cnf,v_fracdate,v_fracdateend,v_state,v_county,v_operator,v_wellname,v_prodtype,v_latitude,v_longitude,v_datum,v_depth,v_water,v_nonwater,v_surfactant,v_tradename,v_supplier,v_purpose,v_ingredients,v_cas,v_additive,v_fluid;
IF done THEN
LEAVE rowloop;
END IF;
SET j = 1;
WHILE j <= v_words DO
-- split tradename and insert row ti Temp1
SET v_tradename_c = TRIM(Split_Str(v_tradename, ',', j));
INSERT INTO Temp1 ( words, id, api, basin, play, drilltype, tradeflag ,score ,cnf, fracdate, fracdateend, state, county, operator, wellname, prodtype, latitude, longitude, datum, depth, water, nonwater, surfactant, tradename, supplier, purpose, ingredients, cas, additive, fluid,
tradename_c )
VALUES ( v_words,v_id,v_api,v_basin,v_play,v_drilltype,v_tradeflag,v_score,v_cnf,v_fracdate,v_fracdateend,v_state,v_county,v_operator,v_wellname,v_prodtype,v_latitude,v_longitude,v_datum,v_depth,v_water,v_nonwater,v_surfactant,v_tradename,v_supplier,v_purpose,v_ingredients,v_cas,v_additive,v_fluid,
v_tradename_c );
SET j = j + 1 ;
END WHILE;
END LOOP rowloop;
CLOSE csr;
RETURN '' ;
END$$