How to use cursor results in a query in stored procedure - stored-procedures

I am trying to get the variable (ACTIVE_INVENTORY) value from sql query dynamically and use it in further below queries. But it seems to be giving error.
Please suggest how could a variable be used in following query.
Thanks
create or replace procedure sp()
returns table (vin varchar, listing_date date, sale_date date, active_inventory boolean)
language sql
as
$$
declare
select_query varchar;
SOLD_THRESHOLD_DATE date;
c1 cursor for select max(sale_date) from TBL;
res resultset;
begin
open c1;
fetch c1 into SOLD_THRESHOLD_DATE;
select_query := 'select vin,listing_date,sale_date,
case when 60 >= DATEDIFF(Day,sale_date,SOLD_THRESHOLD_DATE) then 1 else 0 end as active_inventory from
TBL limit 10';
res:= (execute immediate : select_query);
close c1;
return table(res);
end;
$$;
call sp();
Uncaught exception of type 'STATEMENT_ERROR' on line 13 at position 9 : SQL compilation error: error line 2 at position 41 invalid identifier 'SOLD_THRESHOLD_DATE'

Parametrizing the query:
select_query := 'select vin,listing_date,sale_date,
case when 60>=DATEDIFF(Day,sale_date,?) then 1 else 0 end as active_inventory
from TBL limit 10';
res:= (execute immediate :select_query using (SOLD_THRESHOLD_DATE) );

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;

DB2 - how to call a stored procedure that returns a result set in another user defined table function

I have a db2 stored procedure that takes in some parameters, gets some data from somewhere and then returns a result set through a cursor.
Now I want to write a table function in db2, that will call this stored procedure, read from the result set and return the data in the result set as a table (eventually I want to use this table function in a join).
I would like to know if this is permitted in db2 (we're using DB2 v10.5), i.e. execute a stored procedure in a table function and fetch and read from the result set from the stored procedure. If so, what is the right syntax for calling the stored procedure and reading the result set inside a table function in db2? Thanks!
Yes, it's possible. See the example below.
--#SET TERMINATOR #
CREATE OR REPLACE PROCEDURE TEST_PROC(P_TABSCHEMA VARCHAR(128))
DYNAMIC RESULT SETS 1
READS SQL DATA
BEGIN
DECLARE C1 CURSOR WITH HOLD WITH RETURN FOR
SELECT TABSCHEMA, TABNAME, COLCOUNT
FROM SYSCAT.TABLES
WHERE TABSCHEMA=P_TABSCHEMA;
OPEN C1;
END#
--CALL TEST_PROC('SYSCAT')#
CREATE OR REPLACE FUNCTION TEST_PROC(P_TABSCHEMA VARCHAR(128))
RETURNS TABLE (
TABSCHEMA VARCHAR(128)
, TABNAME VARCHAR(128)
, COLCOUNT INT
)
READS SQL DATA
BEGIN
DECLARE SQLSTATE CHAR(5);
DECLARE V_TABSCHEMA VARCHAR(128);
DECLARE V_TABNAME VARCHAR(128);
DECLARE V_COLCOUNT INT;
DECLARE V1 RESULT_SET_LOCATOR VARYING;
CALL TEST_PROC(P_TABSCHEMA);
ASSOCIATE RESULT SET LOCATOR (V1) WITH PROCEDURE TEST_PROC;
ALLOCATE C1 CURSOR FOR RESULT SET V1;
L1: LOOP
FETCH C1 INTO V_TABSCHEMA, V_TABNAME, V_COLCOUNT;
IF SQLSTATE<>'00000' THEN LEAVE L1; END IF;
PIPE(V_TABSCHEMA, V_TABNAME, V_COLCOUNT);
END LOOP L1;
CLOSE C1;
RETURN;
END#
SELECT * FROM TABLE(TEST_PROC('SYSCAT'))#
You need to create the DB2 table-function as follows:
CREATE FUNCTION database_schema.function_name ( IN_PARTID VARCHAR(1000) )
RETURNS TABLE ( PARTNO CHAR(25), PARTDS CHAR(30), QUANTITY INT )
BEGIN
RETURN SELECT PARTNO , PARTDS , CASE WHEN QUANTITY > 0 THEN QUANTITY ELSE 0 END QUANTITY
FROM
(
SELECT PARTNO
,MAX(PARTDS) AS PARTDS
,SUM(QUANTITY) AS QUANTITY
FROM database_schema.table_name
WHERE 1=1
AND PARTID = (CAST(IN_PARTID AS INT))
GROUP BY PARTNO
) AA;
END;
Then invoke the table-function as join or straight SQL:
SELECT partno,partds,quantity
FROM TABLE(database_schema.function_name('parameter_1'))

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;

Execute immediate in user defined function - called in inner query

I am using a stored procedure to fetch records from an oracle database. This procedure returns paginated records building dynamic SQL query based on search inputs provided. Output 'STATUS' column is derived from user defined function 'GET_STATUS_FOR_ME'. Some derived columns are passed to this function based on this actual status of each record is calculated.
Everything works fine while not providing status as input search criteria. when status is provided it gives me the following error.
ORA-06535: statement string in EXECUTE IMMEDIATE is NULL or 0 length
ORA-06512: at "pkg_search", line 15
06535. 00000 - "statement string in %s is NULL or 0 length"
*Cause: The program attempted to use a dynamic statement string that
was either NULL or 0 length.
*Action: Check the program logic and ensure that the dynamic statement
string is properly initialized.
My user defined function is as below:
FUNCTION GET_STATUS_FOR_ME(
RECORDID IN NUMBER,
ASSIGNEDTO IN NUMBER,
LOCATIONID IN NUMBER,
TEMPUSERID IN NUMBER,
ACTUALSTATUS IN VARCHAR2)
RETURN VARCHAR2
AS
O_STATUS VARCHAR2(200 BYTE);
TEMP_QUERY VARCHAR2(200 BYTE);
I_COUNT NUMBER;
BEGIN
IF LOCATIONID IS NOT NULL AND TEMPUSERID IS NULL THEN
TEMP_QUERY := 'SELECT COUNT(*) FROM MY_TABLE WHERE COUNTRYIF = ' || TO_CHAR(LOCATIONID);
EXECUTE IMMEDIATE TEMP_QUERY INTO I_COUNT;
END IF;
. . . Other FUNCTION logic here. . .
RETURN O_STATUS;
END GET_STATUS_FOR_ME;
My procedure from which this function is being called is as below. This function is being called from inner query.
PROCEDURE SEARCH_RESULT_PROC(
I_LOGGEDINUSERID IN NUMBER,
I_CREATEDFROMDATE IN DATE,
I_CREATEDTODATE IN DATE,
I_STATUS IN VARCHAR2,
I_COUNTRYID IN NUMBER,
I_LANGUAGEID IN NUMBER,
I_OFFSET IN NUMBER,
I_LIMIT IN NUMBER,
I_ORDRBY IN VARCHAR2,
I_SORTBY IN VARCHAR2,
O_COUNT OUT NUMBER,
REF_CUS_RESULTS OUT SYS_REFCURSOR)
AS
PAG_END_ROW NUMBER;
STC_SQL_PART VARCHAR2(9999 BYTE);
DYNMC_SQL_CLAUSE_PART VARCHAR2(9999 BYTE);
BEGIN
PAG_END_ROW := I_OFFSET + I_LIMIT - 1;
STC_SQL_PART := 'select ID, REOCRDSTATUS,
(CASE
some logic here
END) LOCATIONID,
(CASE
some logic here
END) USERID from MY_TABLE MTABLE';
. . Other Logic TO build dynamic WHERE clause depending ON inputs provided. . .
IF I_DOCSTATUS IS NOT NULL THEN
DYNMC_SQL_CLAUSE_PART := DYNMC_SQL_CLAUSE_PART || ' AND UPPER(TEMPDATA.STATUS) = UPPER(''' || I_STATUS || ''')';
END IF;
FINAL_QUERY := 'SELECT ODATA.EID,
ODATA.TITLE,
ODATA.TYPE,
pkg_search.GET_STATUS_FOR_ME(ID,' || I_LOGGEDINUSERID || ',ODATA.LOCATIONID,ODATA.USERID,ODATA.REOCRDSTATUS) STATUS
FROM (SELECT ROWNUM RNUM , TEMP.* FROM ( ' || STC_SQL_PART || DYNMC_SQL_CLAUSE_PART || ' )TEMP WHERE ROWNUM <= ' || TO_CHAR(PAG_END_ROW) ||' ) ODATA WHERE ODATA.RNUM >= '|| TO_CHAR( I_OFFSET) ;
OPEN REF_CUS_RESULTS FOR FINAL_QUERY;
END SEARCH_RESULT_PROC;

DB2 - Declare Cursor in Stored Procedure

I've found this "DECLARE CURSOR" Statement on WWW:
CREATE OR REPLACE PROCEDURE "APART21C"."FIND_VALID_ARZTNRN"
(OUT NoOfRows BIGINT)
RESULT SETS 1
LANGUAGE SQL
SPECIFIC SQL140905135133600
BEGIN
DECLARE myARZTNR CHAR(7);
DECLARE END_TABLE INT DEFAULT 0
;
DELETE FROM APART21C.TMP_LANR07_CHECK
;
DECLARE C1 CURSOR FOR
SELECT DISTINCT Arztnr
FROM APART21C.DMP_LEV_TMP
;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET END_TABLE = 1
;
OPEN C1
;
FETCH C1 INTO myARZTNR
;
WHILE END_TABLE = 0 DO
INSERT INTO APART21C.TMP_LANR07_CHECK
SELECT * FROM TABLE(APART21C.CHECK_ARZTNR_BY_CHECKSUM(myARZTNR)) AS ARZTNRCHECK;
SET NoOfRows = NoOfRows + 1;
FETCH C1 INTO myARZTNR;
END WHILE
;
CLOSE C1
;
END
Errormessage is
"DB2 SQL Error: SQLCODE=-104, SQLSTATE=42601, SQLERRMC=<cursor declaration>;;<SQL statement>"
Need your help, please
I'm a beginner of db2, I've more experience in MS SQL Server.
The statement "SELECT * FROM TABLE(..." calls a function which returns a table.
Problem with the below code
DECLARE C1 CURSOR FOR
SELECT DISTINCT Arztnr
FROM APART21C.DMP_LEV_TMP
I have changed as below and it executed
DECLARE C1 CURSOR WITH HOLD FOR
SELECT Arztnr FROM DMP_LEV_TMP;

Resources