I am calling a DB2 stored proc from BW call procedure pallet.
when i test this proc in database ,it is getting executed properly.
But when i call through BW it throws exception
JDBC error reported: (SQLState = 57014) -
com.ibm.db2.jcc.am.SqlException: DB2 SQL Error: SQLCODE=-952,
SQLSTATE=57014, SQLERRMC=null,
My stored proc's code is as below
CREATE OR REPLACE PROCEDURE TABLE1_PURGE_PROC_V1 (IN v_REF_VERSION VARCHAR(3), OUT o_DELTETE_STATUS VARCHAR(7))
P1: BEGIN
--DECLARE v_TABLE_NAME VARCHAR(30);
DECLARE v_WHERE_CONDITION VARCHAR(1024);
DECLARE V_COUNT_QUERY VARCHAR(1024);
DECLARE v_COMMIT_COUNT INTEGER;
SET v_WHERE_CONDITION='REF_VERSION ='||v_REF_VERSION;
SET v_COMMIT_COUNT=10000;
CALL SCHEMA.DELETE_WITH_COMMIT_COUNT('SCHEMA.TABLE1',v_COMMIT_COUNT,v_WHERE_CONDITION);
CALL SCHEMA.DELETE_WITH_COMMIT_COUNT('SCHEMA.TABLE2',v_COMMIT_COUNT,v_WHERE_CONDITION);
CALL SCHEMA.DELETE_WITH_COMMIT_COUNT('SCHEMA.TABLE3',v_COMMIT_COUNT,v_WHERE_CONDITION);
CALL SCHEMA.DELETE_WITH_COMMIT_COUNT('SCHEMA.TABLE4',v_COMMIT_COUNT,v_WHERE_CONDITION);
INSERT INTO SCHEMA.DEBUG_LOG(PROC_NAME,LOG_TIME,MESSAGE) VALUES('TABLE1_PURGE_PROC_V1',CURRENT_TIMESTAMP,'ALL TABLE1 RELATED TABLES INVALID DATA DELETED FOR VERSION-'||v_REF_VERSION);
SET o_DELTETE_STATUS ='SUCCESS';
END P1
####################################### PROC 2 ###########################################################
CREATE OR REPLACE PROCEDURE DELETE_WITH_COMMIT_COUNT(IN v_TABLE_NAME VARCHAR(24), IN v_COMMIT_COUNT INTEGER, IN v_WHERE_CONDITION VARCHAR(1024))
NOT DETERMINISTIC
LANGUAGE SQL
P1: BEGIN
-- DECLARE Statements
DECLARE SQLCODE INTEGER;
DECLARE v_DELETE_QUERY VARCHAR(1024);
DECLARE v_DELETE_STATEMENT STATEMENT;
SET v_DELETE_QUERY = 'DELETE FROM (SELECT 1 FROM ' || v_TABLE_NAME || ' WHERE ' || v_WHERE_CONDITION
|| ' FETCH FIRST ' || RTRIM(CHAR(v_COMMIT_COUNT)) || ' ROWS ONLY) AS DELETE_TABLE';
PREPARE v_DELETE_STATEMENT FROM v_DELETE_QUERY;
DEL_LOOP:
LOOP
EXECUTE v_DELETE_STATEMENT;
IF SQLCODE = 100 THEN
INSERT INTO TEP.DEBUG_LOG(PROC_NAME,LOG_TIME,MESSAGE) VALUES('DELETE_WITH_COMMIT_COUNT',CURRENT_TIMESTAMP,'ALL DATA DELETED FROM'||v_TABLE_NAME||'QUERY USED IS'||v_DELETE_QUERY);
LEAVE DEL_LOOP;
END IF;
COMMIT;
END LOOP;
COMMIT;
END P1
As I researched ,it is being said that it is the interruption code in DB2.
How to handle this in DB2
I added Tibco timeout to 6 minutes its working now.
deleting 2 million data from 12 tables
Thanks guys for helping
Related
I'm learning to work with PL/SQL procedures. Now I am trying to create table TABLE_T in procedure CREATE_TABLE then I trying to insert data with procedure INSERT_DATA. Inserted data should be modified in procedure MODIFY_DATA.
So data after insertion should look like:
LINE_ID | LINE_MESSAGE
----------------------
1 | 'Hello'
2 | 'Hi'
3 | 'Ciao'
After modification, they should look like:
LINE_ID | LINE_MESSAGE
----------------------
1 | 'Hello world!'
2 | 'Hi world!'
3 | 'Ciao world!'
But the procedure MODIFY_DATA throwing an exception, because allegedly the table does not exist:
Errors: PROCEDURE MODIFY_DATA Line/Col: 4/17 PL/SQL: SQL Statement
ignored Line/Col: 4/51 PL/SQL: ORA-00942: table or view does not exist
Line/Col: 6/6 PL/SQL: Statement ignored Line/Col: 6/66 PLS-00364: loop
index variable 'REC' use is invalid
Errors: PROCEDURE INSERT_DATA Line/Col: 7/5 PL/SQL: Statement ignored
Errors: PROCEDURE CREATE_TABLE Line/Col: 8/5 PL/SQL: Statement ignored
And this is my code:
CREATE OR REPLACE PROCEDURE MODIFY_DATA
IS
BEGIN
FOR REC IN (SELECT LINE_ID, LINE_MESSAGE FROM TABLE_T)
LOOP
EXECUTE IMMEDIATE 'UPDATE TABLE_T SET LINE_MESSAGE = ''' || REC.LINE_MESSAGE || ' world!'' WHERE LINE_ID = ' || REC.LINE_ID;
END LOOP;
END MODIFY_DATA;
/
CREATE OR REPLACE PROCEDURE INSERT_DATA
IS
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO TABLE_T(LINE_ID, LINE_MESSAGE) VALUES (1, ''Hello'')';
EXECUTE IMMEDIATE 'INSERT INTO TABLE_T(LINE_ID, LINE_MESSAGE) VALUES (2, ''Hi'')';
EXECUTE IMMEDIATE 'INSERT INTO TABLE_T(LINE_ID, LINE_MESSAGE) VALUES (3, ''Ciao'')';
MODIFY_DATA;
END INSERT_DATA;
/
CREATE OR REPLACE PROCEDURE CREATE_TABLE
IS
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE TABLE_T ('
|| 'LINE_ID NUMBER NOT NULL,'
|| 'LINE_MESSAGE VARCHAR2(33) NOT NULL,'
|| 'PRIMARY KEY(LINE_ID))';
INSERT_DATA;
END CREATE_TABLE;
/
EXEC CREATE_TABLE;
How can I fix it?
As in your earlier question, table_t still doesn't exist when the modify_data procedure is created - which is what the error is telling you - so it can't be used in a static cursor.
but table is created with immediate command, so it should exist or no ?
It isn't created until the create_table procedure is executed; which is after modify_data is created. When you try to create that procedure the static line:
FOR REC IN (SELECT LINE_ID, LINE_MESSAGE FROM TABLE_T)
is trying to reference the table_t which doesn't yet exist. It doesn't matter that your code implies the execution order - from having create_table call insert_data, and that calling modify_data; which is unusual anyway, it might seem more natural to do this instead:
EXEC CREATE_TABLE;
EXEC INSERT_DATA;
EXEC MODIFY_DATA;
But either way, the problem is when you create modify_data, not when you execute.
You could use a dynamic cursor:
CREATE OR REPLACE PROCEDURE MODIFY_DATA
IS
CUR SYS_REFCURSOR;
TYPE REC_TYPE IS RECORD (
LINE_ID NUMBER,
LINE_MESSAGE VARCHAR2(33)
);
REC REC_TYPE;
BEGIN
OPEN CUR FOR 'SELECT LINE_ID, LINE_MESSAGE FROM TABLE_T';
LOOP
FETCH CUR INTO REC;
EXIT WHEN CUR%NOTFOUND;
EXECUTE IMMEDIATE 'UPDATE TABLE_T SET LINE_MESSAGE = ''' || REC.LINE_MESSAGE || ' world!'' WHERE LINE_ID = ' || REC.LINE_ID;
END LOOP;
CLOSE CUR;
END MODIFY_DATA;
/
db<>fiddle
check your code execution sequence:
EXEC CREATE_TABLE;
EXEC INSERT_DATA;
EXEC MODIFY_DATA;
I try to produce a stored procedure that allows me to update many tables in my database but when I try to execute it with a columnstore engine, i get an error of procedure syntax not supported. I have looked for it in the web but do not manage to find where is the issue. If you have an idea, I let you the procedure here.
DELIMITER $$
CREATE PROCEDURE update_sp_aggregated()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE tableName varchar(255) DEFAULT "";
DECLARE cursor_update
CURSOR FOR
SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_name like 'sp_aggr%' ;
OPEN cursor_update;
updateAggregated: LOOP
FETCH cursor_update into tableName;
IF finished = 1 THEN
LEAVE updateAggregated;
END IF;
SET #sql = CONCAT('ALTER TABLE ', tableName, ' ADD COLUMN col2 varchar(5)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #sql = CONCAT('UPDATE ', tableName, ' SET col2= LEFT(col1, 1)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP updateAggregated;
CLOSE cursor_update;
END $$
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;
DELIMITER ;
CALL update_sp_aggregated();
Finally found, so as tell in my comment, the issue was the update command was not allowed.
to solve it, you need to change the variable infinidb_vtable_mode by setting it to 0.
All is described here
and here
I am trying to build a package that will take in a table of table names and either drop from or delete those tables. I am using dynamic sql, and dropping or deleting the tables works, but I need both the procedures to loop through all of the table names passed back to it.
I've tried mulitple ways - including trying to create a FOR Loop and a cursor. Here is a similar function I wrote in PostgreSQL that works but I'm having trouble translating it to Oracle.
Here is my function in PostgreSQL that works:
CREATE OR REPLACE FUNCTION drop_tables_for_stnd_mod_build(tablenames text)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
tab_name RECORD;
BEGIN
FOR tab_name IN EXECUTE 'SELECT table_name FROM ' || tablenames
LOOP
EXECUTE 'DROP TABLE ' || tab_name.table_name || ' CASCADE';
END LOOP;
END;
$function$
;
And the procedure I'm writing as part of a package in Oracle
CREATE OR REPLACE PACKAGE BODY stnd_build_table_cleanup
AS
PROCEDURE drop_tables(table_in CLOB)
IS
TYPE cur_type is REF CURSOR;
c cur_type;
query_string VARCHAR(300);
loop_string VARCHAR(300);
table_name VARCHAR(100);
BEGIN
loop_string := 'SELECT tablenames FROM :table';
OPEN c FOR loop_string USING table_in;
LOOP
FETCH c INTO table_name;
query_string := 'DROP TABLE ' || table_name || ' CASCADE CONSTRAINTS';
-- dbms_output.PUT_LINE (query_string);
EXECUTE IMMEDIATE query_string;
EXIT WHEN c%NOTFOUND;
END LOOP ;
CLOSE c;
END drop_tables;
Here is the error I get when I try to call my function: Error report -
ORA-00903: invalid table name
ORA-06512: at "AMS_NYS.STND_BUILD_TABLE_CLEANUP", line 13
ORA-06512: at line 2
00903. 00000 - "invalid table name"
*Cause:
*Action:
Thanks!
Here's one possibility. Note that I coded this as a standalone procedure for simplicity.
CREATE OR REPLACE TYPE table_type IS TABLE OF VARCHAR2(128);
CREATE OR REPLACE PROCEDURE drop_tables(tables_to_drop_in table_type)
IS
BEGIN
FOR i IN tables_to_drop_in.FIRST .. tables_to_drop_in.LAST LOOP
--DBMS_OUTPUT.PUT_LINE(tables_to_drop_in(i));
EXECUTE IMMEDIATE 'DROP TABLE ' || tables_to_drop_in(i) || ' CASCADE CONSTRAINTS';
END LOOP;
END drop_tables;
DECLARE
tables_to_drop table_type;
BEGIN
tables_to_drop := table_type('TBL1','TBL2', 'TBL3');
drop_tables(tables_to_drop);
END;
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.
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