DB2 Declare/Set Variable in Stored Procedure - sql

I can't get this stored procedure to compile, I simply want to declare and set one variable that will be used in the proc. NOTE: shipNo is the only incoming parameter, and is VARCHAR(32).
P1: BEGIN
DECLARE #likeShipNo VARCHAR(32);
SET likeShipNo = '%' || shipNo || '%';
DECLARE cursor1 CURSOR WITH RETURN FOR
SELECT ADV_SHIP_NOTICE_NO,
VNDR_ID,
LOC,
CARR_CD,
CARR_PRO_NO,
BL_NO,
SHIP_EQUIP_ID,
TS_LOAD
FROM TRITS
WHERE ADV_SHIP_NOTICE_NO LIKE(#likeShipNo);
OPEN cursor1;
END P1

The variables in DB2 doesn't need the # like in MSSQL. Also, when you return a cursor, you need to add the sentence RESULT SET 1 before begin and add the WITH RETURN TO CLIENT to the cursor that you want to return. The procedure should look like this:
CREATE BEGIN MYSCHEMA.MYPROC (
IN shipNo VARCHAR(30) )
BEGIN
DECLARE likeShipNo VARCHAR(32);
SET likeShipNo = '%' || shipNo || '%';
DECLARE cursor1 CURSOR WITH RETURN TO CLIENT FOR
SELECT
ADV_SHIP_NOTICE_NO,
VNDR_ID,
LOC,
CARR_CD,
CARR_PRO_NO,
BL_NO,
SHIP_EQUIP_ID,
TS_LOAD
FROM
TRITS
WHERE
ADV_SHIP_NOTICE_NO LIKE likeShipNo;
OPEN cursor1;
END;

Related

Creating a procedure with a call to another procedure in teradata

I have a procedure that returns a list when requested - test_1.
I want to create a procedure that sends each value from a table type_cd_list to the procedure test_1 and returns a list, but I get an error:
An existing result set Cursor is opened from stored procedure
Code:
--calling procedures
CALL Pb_tmd.test_1('280');
--create table
CREATE VOLATILE TABLE type_cd_list
(
num_chn VARCHAR(10),
info_system_type_cd VARCHAR(10)
) ON COMMIT PRESERVE ROWS;
INSERT INTO type_cd_list ('12','280');
--procedure
REPLACE PROCEDURE Pb_tmd.test_2()
DYNAMIC RESULT SETS 1
BEGIN
DECLARE hc1 VARCHAR(10);
FOR
RepordPointer AS c_sptable CURSOR FOR
SELECT info_system_type_cd AS c_c1 FROM type_cd_list
DO
SET hc1 = RepordPointer.c_c1;
CALL Pb_tmd.test_1(:hc1);
END FOR;
ROLLBACK;
END;
Or is there another option to combine these 2 procedures? Below is the nested procedure code
REPLACE PROCEDURE Pb_tmd.test_1 (IN db_lst VARCHAR(100))
DYNAMIC RESULT SETS 1
BEGIN
DECLARE NumberInst VARCHAR(100);
DECLARE SQL_TEXT VARCHAR(3000);
DECLARE cur1 CURSOR WITH RETURN ONLY FOR S1;
SET SQL_TEXT = 'SELECT * FROM Pb_'||db_lst||'_tmd.LOAD_LOG';
PREPARE S1 FROM SQL_TEXT;
OPEN cur1;
END;

db2 dynamic cursor declaration

I am trying to create a stored procedure, but I get this error
Expected tokens may include: "". LINE NUMBER=17. SQLSTATE=42601
My code:
CREATE OR REPLACE PROCEDURE FETCH_EMP_SP(IN V_EMP_NAME VARCHAR(100),IN V_EMP_DEPT VARCHAR(100))
DYNAMIC RESULT SETS 1
LANGUAGE SQL
BEGIN
DECLARE p_query_string VARCHAR(100);
IF ((V_EMP_NAME IS NOT NULL) AND (V_EMP_DEPT IS NOT NULL)) THEN
SET p_query_string = 'emp_name ='||V_EMP_NAME||' AND emp_dept='||V_EMP_DEPT||' WITH UR';
ELSEIF(V_EMP_DEPT IS NOT NULL) THEN
SET p_query_string = ' AND emp_dept='||V_EMP_DEPT||' WITH UR';
ELSE
SET p_query_string = ' WITH UR';
END IF;
DECLARE C1 CURSOR WITH RETURN TO CLIENT FOR SELECT emp_name,emp_no,emp_dept,emp_location from employee where status=1 p_query_string;
OPEN C1;
END#
should be executed successfully
Declarations and statements can’t follow in arbitrary order in a Compound SQL (compiled) statement
Cursor declarations must follow the variables declarations and must be followed by the SQL procedure statements.
So, place the cursor declaration after the variable declaration.
Moreover, there is a number of other errors in your code. Should be something like this:
CREATE OR REPLACE PROCEDURE FETCH_EMP_SP(IN V_EMP_NAME VARCHAR(100),IN V_EMP_DEPT VARCHAR(100))
DYNAMIC RESULT SETS 1
LANGUAGE SQL
BEGIN
DECLARE p_query_string VARCHAR(256);
DECLARE C1 CURSOR WITH RETURN TO CLIENT FOR S1;
IF ((V_EMP_NAME IS NOT NULL) AND (V_EMP_DEPT IS NOT NULL)) THEN
SET p_query_string = ' AND emp_name ='''||V_EMP_NAME||''' AND emp_dept='''||V_EMP_DEPT||''' WITH UR';
ELSEIF(V_EMP_DEPT IS NOT NULL) THEN
SET p_query_string = ' AND emp_dept='''||V_EMP_DEPT||''' WITH UR';
ELSE
SET p_query_string = ' WITH UR';
END IF;
SET p_query_string='SELECT emp_name,emp_no,emp_dept,emp_location from employee where status=1 '||p_query_string;
PREPARE S1 FROM p_query_string;
OPEN C1;
END#
String constants in the query text must be wrapped in single quotes. Don't do this if emp_dept is a numeric column.

Two cursors sequence in procedure

I have the following problem with a procedure:
CREATE PROCEDURE TEST()
LANGUAGE SQL
BEGIN
DECLARE V_TEST VARCHAR(100);
DECLARE V_TEST_EXT VARCHAR(100);
DECLARE SQLCODE INTEGER DEFAULT -1;
DECLARE RET_CODE INTEGER DEFAULT -2;
DECLARE LIST_CMD VARCHAR(512);
DECLARE LIST_CMD_EXT VARCHAR(512);
DECLARE CUR_TEST CURSOR WITH RETURN FOR LIST_STMT;
DECLARE CUR_TEST_EXT CURSOR WITH RETURN FOR LIST_EXT_STMT;
DECLARE CONTINUE HANDLER FOR SQLEXECPTION SET RET_CODE = SQLCODE;
SET LIST_CMD = 'SELECT TEST FROM TESTTAB';
PREPARE LIST_STMT FROM LIST_CMD;
OPEN CUR_TEST;
FETCH CUR_TEST INTO V_TEST;
WHILE (RET_CODE <> 100) DO
FETCH CUR_TEST INTO V_TEST;
END WHILE;
CLOSE CUR_TEST;
SET LIST_CMD_EXT = 'SELECT TEST FROM TESTTAB';
PREPARE LIST_STMT_EXT FROM LIST_CMD_EXT;
OPEN CUR_TEST_EXT;
FETCH CUR_TEST_EXT INTO V_TEST_EXT;
WHILE (RET_CODE <> 100) DO
FETCH CUR_TEST_EXT INTO V_TEST_EXT;
END WHILE;
CLOSE CUR_TEST_EXT;
END;
The problem I am having is that the procedure does the first cursor loop but ignores the second one. I tried adding BEGIN and END to each loop but that didn't help as well.
I am running DB2 v10.5 Windows. I need this to work as a procedure. Is there any way to make the procedure run both loops?
Thank you for your help.-
You don't reset the RET_CODE variable before processing the 2-nd cursor.
Use something like this:
SET RET_CODE = 0;
OPEN CUR_TEST_EXT;
...
BTW, don't declare a cursor using 'WITH RETURN' clause if you process this cursor inside the procedure.

DB2 dynamic table name

I want to count the rows of a number of tables. But the table name should be used dynamically. I want to do that within one SQL statement.
I tried it with
BEGIN ATOMIC
FOR tmp AS (
SELECT tabschema || '.' || tabname tbl
FROM syscat.tables WHERE tabname LIKE '%CD') DO
(SELECT COUNT(*) FROM tmp.tbl);
END FOR;
END
but I receive the error
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL0204N "TMP.TBL" is an undefined name. LINE NUMBER=1. SQLSTATE=42704
and found no other working solution...
Is there a solution for that?
Thanks in advance.
I assume that your SELECT COUNT(*) FROM tmp.tbl should translate in multiple statements like
select count(*) from TABLECD
select count(*) from TABLE2CD
...
However, your query will try to do a count of the table TBL in the schema TMP.
You'll have to prepare the complete SQL statement, store it in a variable and pass it to the PREPARE statement (documentation ).
A rather complete stored procedure which somewhat fits your requirements can be found here . The result of the counts will be stored in a table COUNTERS which you can query afterwards.
//edit: this is the example from the topic, adapt to work (not tested since I have no DB2 instance to test atm):
CREATE PROCEDURE tableCount()
LANGUAGE SQL
BEGIN
DECLARE SQLCODE INTEGER DEFAULT 0;
DECLARE SQLSTATE CHAR(5);
DECLARE vTableName VARCHAR(20);
DECLARE vTableCount INTEGER;
DECLARE stmt varchar(2000);
DECLARE not_found CONDITION FOR SQLSTATE '02000';
DECLARE c1 CURSOR FOR
SELECT tabname from syscat.tables where tabschema='DB2ADMIN';
DECLARE C2 CURSOR FOR S2
DECLARE CONTINUE HANDLER FOR not_found
SET stmt = '';
Delete from COUNTERS;
OPEN c1;
getRows:
LOOP
FETCH c1 INTO vTableName;
IF SQLCODE = 0 THEN
SET stmt ='SELECT Count(*) FROM ' || vTableName;
PREPARE S2 FROM stmt;
OPEN C2;
SET vTableCount = 0;
FETCH C2 INTO vTableCount;
INSERT INTO COUNTERS (tableName, tableCount)
VALUES (vTableName, vTableCount);
CLOSE C2;
ELSE
LEAVE getRows;
END IF;
END LOOP getRows;
CLOSE c1;
END

Delphi - pass table valued parameter to SQL Server stored procedure

I need to pass the parameter as table value for a stored procedure in SQL Server. How to handle this in Delphi?
As far as I know there in no simple way to pass Table parameters, using the components shipped with Delphi.
A workaround would be using a temporary table which can be used to fill a typed table variable.
Assuming your definition would look like this:
CREATE TYPE MyTableType AS TABLE
( ID int
, Text varchar(100) )
GO
CREATE PROCEDURE P_Table
#Tab MyTableType READONLY
AS
BEGIN
SET NOCOUNT ON;
Select * from #Tab -- dummy operation just return the dataset
END
GO
You could call the procedure like this:
var
i: Integer;
begin
// we create a temporary table since a table variable can obly be used for a single call
DummyDataset.Connection.Execute('Create Table #mytemp(ID int,Text varchar(100))');
DummyDataset.CommandText := 'Select * from #mytemp';
DummyDataset.Open;
for i := 0 to 10 do
begin
DummyDataset.Append;
DummyDataset.Fields[0].Value := i;
DummyDataset.Fields[1].Value := Format('A Text %d', [i]);
DummyDataset.Post;
end;
MyDataset.CommandText := 'Declare #mytemp as MyTableType '
+ 'Insert into #mytemp select * from #mytemp ' // copy data to typed table variable
+ 'EXEC P_Table #Tab = #mytemp';
MyDataset.Open;
DummyDataset.Connection.Execute('Drop Table #mytemp');
end
The sample downloadable from http://msftdpprodsamples.codeplex.com/wikipage?title=SS2008%21Readme_Table-Valued%20Parameters is written in C++ but could readily be translated to Delphi.
Once you have translated that code to Delphi, you can use something like the following to make the result set accessible via good ole ADO:
SourcesRecordset := CreateADOObject(CLASS_Recordset) as _Recordset;
RSCon := SourcesRecordset as ADORecordsetConstruction;
RSCon.Rowset := rowset;
LDataSet := TADODataSet.Create(nil);
try
// Only doing the first result set
LDataSet.Recordset := SourcesRecordset;
while not LDataSet.Eof do
begin
//... something
LDataSet.Next;
end;
finally
LDataSet.Free;
end;
Note that CreateADOObject is a private function in Data.Win.ADODB.pas but it's pretty trivial.