MySQL Procedure to retrieve missing auto increment ID of a table? - stored-procedures

I create a procedure to find out missing id from a table, But it does not retrieve any result, below are the procedure
DELIMITER ||
DROP PROCEDURE IF EXISTS proc_rpt ||
CREATE PROCEDURE proc_rpt()
BEGIN
SET #minID = (SELECT MIN(`id`) FROM `tbl_film` WHERE `user_id`=13);
SET #maxID = (SELECT MAX(`id`) FROM `tbl_film` WHERE `user_id`=13);
REPEAT
SET #tableID = (SELECT `id` FROM `tbl_film` WHERE `id` = #minID);
IF (#tableID IS NULL) THEN
INSERT INTO temp_missing(`missing_id`) VALUES (#tableID);
END IF;
SET #minID = #minID + 1;
UNTIL (#minID <= #maxID)
END REPEAT; // earlier I was missing this line which was giving error in Procedure.
END; ||
Then i call above
CALL rpt_proc();
But there are no result on tbl_missing while i can see there are many missing values of film_id in tbl_film. Will someone please tell me what I am doing wrong?

Have a try with this code.
DELIMITER ||
DROP PROCEDURE IF EXISTS proc_rpt ||
CREATE PROCEDURE proc_rpt()
BEGIN
DECLARE maxId int;
DECLARE minId int;
DECLARE curId int;
SELECT MIN(`id`) INTO maxId FROM `tbl_film` WHERE `user_id`=13;
SELECT MAX(`id`) INTO minId FROM `tbl_film` WHERE `user_id`=13;
REPEAT
SELECT `id` INTO curId FROM `tbl_film` WHERE `id` = #minID);
IF (curId IS NULL) THEN
INSERT INTO temp_missing(`missing_id`) VALUES (curId);
END IF;
SET minId = minId + 1;
UNTIL (minId <= maxId)
END REPEAT; // earlier I was missing this line which was giving error in Procedure.
END; ||

Related

Dynamic Insert through Teradata Stored procedure

I am trying to run Insert statement to load data into table using Teradata Stored procedure. Here I am trying to Input Table Name, Databasename as Parameter. My stored procedure compiled and ran well. But its not inserting any data into table. Could someone please help me with this. Below is the query I am using..
REPLACE PROCEDURE DB.TEST_SP
(
IN SRC_DB_NM VARCHAR(30)
, IN SRC_TBL_NM VARCHAR(30)
, OUT MESSAGE VARCHAR(200)
)
DYNAMIC RESULT SETS 1
BEGIN
DECLARE QUERY1 VARCHAR(200);
DECLARE RESULT1 VARCHAR(200);
DECLARE REC_COUNT INTEGER DEFAULT 0;
DECLARE STATUS CHAR(10) DEFAULT '00000';
DECLARE C1 CURSOR FOR S1;
DECLARE EXIT HANDLER FOR SQLEXCEPTION,SQLWARNING
BEGIN
SET STATUS = SQLCODE;
IF(TRIM(STATUS)) = '3807' THEN
SET MESSAGE = 'PASSED TABLE '||SRC_DB_NM||'.'||SRC_TBL_NM||' DOES NOT EXIST';
ELSE
SET MESSAGE = 'LOADED';
END IF;
END;
BEGIN
SET QUERY1 ='INSERT INTO TABLE1 SELECT ColX , count(*) from DB.table2 where Col in ( SELECT Col1 FROM ' || SRC_DB_NM || '.' || SRC_TBL_NM || ' where ColY = 999 ) group by 1;' ;
EXECUTE IMMEDIATE QUERY1;
PREPARE S1 FROM QUERY1;
OPEN C1 USING SRC_DB_NM,SRC_TBL_NM;
FETCH C1 INTO RESULT1;
SET MESSAGE = RESULT1;
END;
END;

How can I create a stored procedure to only allow inserts in a particular month?

I want to create a stored procedure that only does inserts in the month of March. The stored procedure should accept values for the table but use the system date to determine if the records should be inserted.
This is what I was trying but procedure created with errors.
CREATE OR REPLACE PROCEDURE sp_time_1203383 (
p_sales_id IN sales_1203383.SALES_ID%TYPE,
p_product IN sales_1203383.PRODUCT%TYPE,
p_unitcost IN sales_1203383.UNITCOST%TYPE,
p_quantity IN sales_1203383.QUANTITY%TYPE
)
IS
BEGIN
IF( MONTH( GETDATE() ) = 3 )
BEGIN
INSERT INTO sales_1203383 ("SALES_ID", "PRODUCT", "UNITCOST", "QUANTITY")
VALUES (p_sales_id, p_product,p_unitcost, p_quantity);
END
ELSE
BEGIN
SELECT 'Can Only insert during the month of March'
END
COMMIT;
END;
I think Praveen gave you the right advice.
I personally would not use the
SELECT count(1) into v_cnt FROM dual WHERE month(sysdate) = 3;
but you can check in a if ... then ... else ... end; statement with the following code:
if to_char(sysdate,'mm') = '03' then ... end;
There are a few errors in your stored procedure:
You cannot have select with if statement
Use then with IF statement and at end End if
; has to be used with End statement
You cannot return a select set from a procedure/function/block (ref cursor should be used)
If you want raise error in the else part use raise_application_error.
If your select statement is like select 'something' use dummy table dual, select 'something' from dual
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
CREATE OR REPLACE PROCEDURE sp_time_1203383 (
p_sales_id IN sales_1203383.SALES_ID%TYPE,
p_product IN sales_1203383.PRODUCT%TYPE,
p_unitcost IN sales_1203383.UNITCOST%TYPE,
p_quantity IN sales_1203383.QUANTITY%TYPE
)
IS
v_cnt NUMBER;
BEGIN
SELECT count(1) into v_cnt FROM dual WHERE month(sysdate) = 3;
IF v_cnt > 0 THEN
INSERT INTO sales_1203383 ("SALES_ID", "PRODUCT", "UNITCOST", "QUANTITY")
VALUES (p_sales_id, p_product, p_unitcost, p_quantity);
ELSE
raise_application_error(-20101, 'Can Only insert during the month of March');
END IF;
END;

Procedure runs,but doesn't do anything

I have a little problem with running a certain procedure in MariaDB.
The funny thing is that when i run the procedure,it doesn't show any errors,but unfortunately it doesn't do anything.
And I can't simply find what's wrong.
Guys please help.Thx
Query:
CREATE DEFINER=`root`#`127.0.0.1` PROCEDURE `p_tun_removal`(IN `GeoTerID` INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
BEGIN
DECLARE #done INT DEFAULT FALSE;
DECLARE #CurrentVersion INT;
DECLARE #CorrectVersion INT;
DECLARE #BeginVersion INT;
DECLARE cur1
CURSOR FOR
SELECT Distinct(Version)
FROM geo_patch
WHERE TerID = GeoTerID AND Version >= BeginVersion;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
declare exit handler for sqlexception
begin
rollback;
resignal;
end;
CREATE Temporary TABLE `tunnel_temp` (
`ID` INT NOT NULL
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
insert into tunnel_temp ( ID ) (
SELECT ID from geo_patch
WHERE Version in ( select Version from geo_patch where Substance = 0 ) and TerID = GeoTerID
);
SET #BeginVersion = ( SELECT Version from geo_patch where ID = ( SELECT ID from tunnel_temp limit 1 ) ) - 1 ;
SET #CorrectVersion = #BeginVersion;
IF (#CorrectVersion < 2) THEN
SET #CorrectVersion = 2;
END IF;
START TRANSACTION;
DELETE FROM geo_patch where ID in ( Select ID from tunnel_temp );
open cur1;
version_loop: LOOP
FETCH cur1 into #CurrentVersion;
IF done THEN
LEAVE version_loop;
END IF;
UPDATE geo_patch SET Version = #CorrectVersion WHERE Version = #CurrentVersion;
SET CorrectVersion = CorrectVersion + 1;
END LOOP;
close cur1;
COMMIT;
UPDATE terrain_blocks SET GeoVersion = ( select Version from geo_patch where TerID = GeoTerID order by Version desc limit 1 ) WHERE ID = GeoTerID;
drop temporary table if exists tunnel_temp;
END
Don't use the construct IN ( SELECT ... ), use a JOIN instead.
Try to avoid cursors by doing the entire operation in a single statement.

Stored Procedure not returning data based on IF condition

I have a stored procedure in which I am checking if a table returns any rows. If no rows are returned then just return an empty/dummy result set. If rows are returned then return the same result set.
Here's the procedure
BEGIN
Declare #HAS_ROWS int
SELECT #HAS_ROWS(SELECT COUNT(*) AS HAS_ROWS FROM Table1)
If(#HAS_ROWS <= 0)
BEGIN
SELECT TOP 1 NULL FROM Table1
Return
END
Else
BEGIN
SELECT * FROM Table1
Return
END
END
Upon running this procedure I get the following result
(No column name)
0
HAS_ROWS
NULL
Title
This is title of row1
This is title of row2
As you can see it is returning 3 result sets and I expect it to return on only based on IF condition. What am I doing wrong?
#Aaron is right with the #Has_Rows - it needs to be assigned with SELECT #HAS_ROWS = ... or SET #HAS_ROWS = ... (the latter has more restrictions on use).
Here is a fixed / simplified version that should work for you:
BEGIN
IF((SELECT COUNT(*) FROM Table1) = 0)
SELECT NULL
ELSE
SELECT * FROM Table1
RETURN
END

Firebird and stored procedures: if exists then else

I'm trying to create a stored procedure for firebird 2.1 (this is the version which is to be used)
But am getting a bit stuck, so any help is appreciated.
The final version should compare 4 values agains the table, and retreive either the primaryid if the value exists, or create the new entry in the table, and return the new primaryid.
But I get stuck with only one value lookup, and it's not even using the variable yet.
SET TERM ^ ;
CREATE PROCEDURE TESTSP
( A Varchar(64) )
RETURNS
( RESULT Integer )
AS
BEGIN
IF (EXISTS (SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string')) then
SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string' into :primaryid;
result = PRIMARYID;
ELSE
INSERT INTO TABLENAME (FIELD) VALUES ('Some string');
result = gen_id(GEN_TABLEID, 0);
END^
SET TERM ; ^
I get a "Token unknown" for the Else command.
Update after responses:
Now I want to use the 4 variables and return the 4 results.
I think I need a for loop to do so, but with firebird, the for function means something else.
So what would be the way to go?
SET TERM ^ ;
CREATE PROCEDURE TESTSP
( value1 Varchar(64) )
RETURNS
( RESULT1 Integer )
AS
BEGIN
IF (EXISTS (SELECT PRIMARYID FROM TABLENAME WHERE FIELD = :value1)) then
SELECT PRIMARYID FROM TABLENAME WHERE FIELD = value1 into :result1;
ELSE BEGIN
result1 = gen_id(GEN_TABLEID, 1);
INSERT INTO TABLENAME (PRIMARYID, FIELD) VALUES (:result1, :value1);
END
suspend;
END^
SET TERM ; ^
As Tico already answered you have to use begin / end to group multiple statements in then / else part. The error abut column PRIMARYID being unknown is because you reference to it without having declared a local variable for it. Try this:
CREATE PROCEDURE TESTSP ( A Varchar(64) )
RETURNS ( RESULT Integer )
AS
BEGIN
-- initialize the result
Result = NULL;
-- check is the string already in table
SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string' into :Result;
IF (Result is NULL) then
INSERT INTO TABLENAME(PRIMARYID, FIELD) VALUES(gen_id(GEN_TABLEID, 1), 'Some string') RETURNING PRIMARYID INTO :Result;
END^
I think your stored procedure should look like this:
SET TERM ^ ;
CREATE PROCEDURE TESTSP
( A Varchar(64) )
RETURNS ( result Integer )
AS
BEGIN
IF (EXISTS (SELECT PRIMARYID
FROM TABLENAME
WHERE FIELD = 'Some string')) then
SELECT PRIMARYID
FROM TABLENAME
WHERE FIELD = 'Some string'
into :result;
ELSE BEGIN
result = gen_id(GEN_TABLEID, 1);
INSERT INTO TABLENAME
(PRIMARYID, FIELD)
VALUES (:result, 'Some string');
END
END^
SET TERM ; ^
If you have multiple instruction for then and/ or else clause you must use BEGIN ... END-block!
SET TERM ^ ;
CREATE PROCEDURE TESTSP
( A Varchar(64) )
RETURNS
( RESULT Integer )
AS
BEGIN
IF (EXISTS (SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string')) then
BEGIN
SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string' into :primaryid;
result = PRIMARYID;
END
ELSE
BEGIN
INSERT INTO TABLENAME (FIELD) VALUES ('Some string');
result = gen_id(GEN_TABLEID, 0);
END
END^
SET TERM ; ^

Resources