Informatica pre sql to drop an index - sql

I am trying to load 2 million records into a oracle table using the Oracle external loader in Informatica. In order to load the data, I am trying to drop the index on the table and re create after the data is loaded. I am using the below anonymous block in the pre SQL in mapping for the target:
Declare indxcnt int\;
BEGIN
SELECT COUNT(INDEX_NAME)
INTO indxcnt
FROM all_INDEXES WHERE INDEX_NAME = 'TEST_INDEX1'\;
IF indxcnt > 0 THEN
Execute Immediate 'DROP INDEX TEST_INDEX1'\;
END If \;
END\;
However the pre SQL is not working and as the index is not getting dropped.
When I use the same anonymous block in the session properties using the relation writer, it is working fine.
Kindly help me how to drop and re create the index while using the loader to load the table.

At the end of the software you want to execute. You can do it by /:
This is in PL/SQL. I don't know informatica but perhaps this could help you.
DECLARE
indxcnt NUMBER;
BEGIN
--
SELECT COUNT(INDEX_NAME)
INTO indxcnt
FROM all_indexes WHERE index_name = 'TEST_INDEX1';
--
IF indxcnt > 0
THEN
EXECUTE IMMEDIATE 'DROP INDEX TEST_INDEX1';
END IF;
END;
/

Related

PL/SQL: Creation and usage of a temporary table in script

On an Oracle 19c DB I need to sample on customers whilst keeping a uniorm distribution to model the moving of customers.
There are (on purpose) multiple rows with the same customers but changeing adderssses to model moving. Thus, for the sampling i need to group first.
Now what I got is that for the SAMPLE clause the source has to be materialized. So in the PL/SQL script I generate a temporary table that i want to use afterwards with SAMPLE.
But even a simple SELECT INTO afterwards doens't work.
set SERVEROUT on;
DECLARE
v_cust_name VARCHAR2(100);
cmd_creation VARCHAR2(500):='CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp_cust AS(
SELECT cust_id, MIN(name) as name
FROM customers
GROUP BY cust_id)';
BEGIN
EXECUTE IMMEDIATE cmd_creation;
dbms_output.put_line('temp created');
SELECT name
INTO v_cust_name
FROM (SELECT *
FROM ORA$PTT_temp_cust SAMPLE(5))
WHERE ROWNUM =1;
EXECUTE IMMEDIATE 'DROP TABLE ORA$PTT_temp_cust';
dbms_output.put_line('temp dropped');
END;
What I get is this
ORA-06550: line 15, column 18:
PL/SQL: ORA-00942: table or view does not exist
The table gets created. That far I got when I only executed the String for the creation and nothing else. Then I can access the table in a desired script from a different point.
Does this have to do with the compiling? Is there some different way to solve this?
Your PL/SQL Block simple does not compile as the table you query does not exists at the time of compilation.
You must perform event the query with execute immediate
Simplified Example
DECLARE
v_cust_name VARCHAR2(100);
cmd_creation VARCHAR2(500):='CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp_cust AS select * from dual';
BEGIN
EXECUTE IMMEDIATE cmd_creation;
dbms_output.put_line('temp created');
EXECUTE IMMEDIATE 'SELECT DUMMY FROM ORA$PTT_temp_cust' INTO v_cust_name;
dbms_output.put_line('name' || v_cust_name);
EXECUTE IMMEDIATE 'DROP TABLE ORA$PTT_temp_cust';
dbms_output.put_line('temp dropped');
END;
/
An other caveat the can lead to ORA-00942: table or view does not existin your setup is that you performs commit in your script.
The default definition of the ON COMMIT clause is DROP DEFINITION so you must use
CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp_cust
ON COMMIT PRESERVE DEFINITION
...
Dynamic SQL is evil. The fact that you created the table using dynamic SQL (your 1st execute immediate) doesn't mean that Oracle "predicts" you'll actually succeed with that and "presume" that statements that follow are correct. Nope - that table doesn't exist yet, so everything has to be moved to dynamic SQL.
Something like this (disregard changes in table and column names I used and global vs. private temporary table; this is 11gXE):
SQL> DECLARE
2 v_cust_name VARCHAR2 (100);
3 cmd_creation VARCHAR2 (500)
4 := 'CREATE global TEMPORARY TABLE PTT_temp_cust AS
5 SELECT empno, MIN(ename) as name
6 FROM emp
7 GROUP BY empno';
8 BEGIN
9 EXECUTE IMMEDIATE cmd_creation;
10
11 EXECUTE IMMEDIATE '
12 SELECT max(name)
13 FROM (SELECT *
14 FROM PTT_temp_cust SAMPLE(5))
15 WHERE ROWNUM = 1'
16 INTO v_cust_name;
17
18 EXECUTE IMMEDIATE 'DROP TABLE PTT_temp_cust';
19
20 DBMS_OUTPUT.put_line ('Result = ' || v_cust_name);
21 END;
22 /
Result =
PL/SQL procedure successfully completed.
SQL>
I got no result, though - but you should (at least, I hope so).

How to execute alter command within select statement in a loop in Oracle?

I am trying to Rebuild Indexes of a schema through a script but I am stucked at a point where I get the string ALTER INDEX OWNER.INDEX_NAME REBUILD NOLOGGING through select statement but I am not getting how to execute the alter command ,please guide :
I tried to assign str the value of select query used in 2nd for loop and then execute it but it gave error .
IS
STR VARCHAR2(5000);
BEGIN
FOR T IN (
SELECT USERNAME FROM DBA_USERS WHERE USERNAME ='REPORT'
)
LOOP
FOR CUR IN
(
SELECT ' ALTER INDEX '||OWNER||'.'||INDEX_NAME|| ' REBUILD NOLOGGING; ' FROM DBA_INDEXES
WHERE OWNER=T.USERNAME AND TEMPORARY='N'
)
LOOP
--- EXECUTE IMMEDIATE STR ;
INSERT INTO INDEX_REBUILD_HISTORY
SELECT DISTINCT OWNER, TRUNC(LAST_DDL_TIME) from DBA_OBJECTS where OBJECT_TYPE = 'INDEX'
AND
OWNER=T.USERNAME ;
COMMIT;
END LOOP;
END LOOP;
END ;
You use dynamic sql. And you don't need your outer loop. The filter on that is available in dba_indexes:
create procedure bld_idx
is
vsql varchar2(500);
for x in (select owner,
index_name
from dba_indexes
where owner = 'REPORT'
and TEMPORARY='N'
)
loop
vsql := ' ALTER INDEX '||x.OWNER||'.'||x.INDEX_NAME|| ' REBUILD NOLOGGING; ';
dbms_output.put_line(vsql); -- debugging only
execute immediate vsql;
end loop;
end;
Note 1: above is off the top of my head. There may be minor syntax issues, but if so you should be able to work them out.
Not 2: Rebuilding indexes is not something that needs to be done in the normal course of things. Richard Foote is probably the foremost authority on the internals of oracle indexes, and he has this to say: https://richardfoote.wordpress.com/2007/12/11/index-internals-rebuilding-the-truth/
"it gave error ." isn't helpful without the actual error you received. That said you've made the same mistake so many others do, you shouldn't include the ";" as part of your dynamic SQL - it's not part of the statement, it's only used by your client to know when to send code to the database.
FOR CUR IN
(
SELECT ' ALTER INDEX '||OWNER||'.'||INDEX_NAME|| ' REBUILD NOLOGGING' ddl_cmd FROM DBA_INDEXES
WHERE OWNER=T.USERNAME AND TEMPORARY='N'
)
...
EXECUTE IMMEDIATE CUR.ddl_cmd ;
(I've also given the column an alias so you can use it in your loop nicely.
Then
INSERT INTO INDEX_REBUILD_HISTORY
SELECT DISTINCT OWNER, TRUNC(LAST_DDL_TIME) from DBA_OBJECTS where OBJECT_TYPE = 'INDEX'
AND
OWNER=T.USERNAME ;
Is not filtering on the index you just rebuilt, it doesn't seem like it's going to get entirely useful information.
That said...
Is it really worth rebuilding all your indexes offline and making them unrecoverable? Probably not, if you're doing this more than once and are benefiting then there's probably something that could be changed with your data model to help. Have a good read of this presentation by Richard Foote, a well established Oracle Indexing Expert https://richardfoote.files.wordpress.com/2007/12/index-internals-rebuilding-the-truth.pdf I doubt you'd come away from it believing that rebuilding all the indexes is a solution.

creating temp table

i want to create one temp table in procedure and use that table in that procedure only after finishing to execute that 'SP' then automatically delete that table so how can i do that one?
You can you the dynamic SQL
execute immediate 'create table my_table (/* cols here */)';
and at the end:
execute immediate 'drop table my_table';
Also worth mentioning, you can't compile the code while using the temp table directly as table is not present at compile time. You have to use dynamic SQL in order to use it.
You can use dynamic sql
Execute immediate 'create table...'
Then you can do your staf
After all all of them in same way you can drop table
execute immediate 'drop table....

How to delete data from specified tables at once in oracle sql

I have more than 40 tables in RATOR_MONITORING schema for which the table name is starting from 'TEMP_'. I want to delete data from all such tables at once in a single query instead of using delete statement for each and every table. I dont even want to generate statements. I can create anonymous block if required but dont know how to do that. I tried below query but its not working.
Delete from RATOR_MONITORING_CONFIGURATION.'%TEMP_';
If you want to delete all the rows, then better use TRUNCATE, it will reset the high watermark. But remember, truncate is a DDL statement, and thus there will be an implicit commit; With DELETE you can commit manually after validation.
Although, I would not do that in a production environment. If it is something you are doing in test environment to build test data, then you could (ab)use EXECUTE IMMEDIATE.
For example, execute the following anonymous block as RATOR_MONITORING user:
DECLARE
v_sql VARCHAR2(100);
BEGIN
FOR i IN
(SELECT table_name FROM user_tables where table_name like 'TEMP%'
)
LOOP
v_sql := 'TRUNCATE TABLE '||i.table_name;
EXECUTE immediate v_sql;
END LOOP;
END;
/
By the way, using a good text editor, it won't take more than a minute to build DELETE/TRUNCATE statements and do it in pure SQL.

Create or replace table in Oracle pl/sql

I need a script which creates table or if it already exist drops it, and when recreates table. After some research I have found out that CREATE OR REPLACE TABLE in pl/sql doesn't exist. So I come up with this script :
DECLARE
does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT (does_not_exist, -942);
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE foobar';
EXCEPTION
WHEN does_not_exist
THEN
NULL;
END;
/
CREATE TABLE foobar (c1 INT);
Is there any proper way to achieve this functionality?
You really shouldn't be doing this in PL/SQL, tables created at runtime would be indicative of a flaw in your data model. If you're really convinced you absolutely have to do this then investigate temporary tables first. Personally, I'd reassess whether it's necessary at all.
You seem to be going for the EAFP as opposed to LBYL approach, which is described in a few answers to this question. I would argue that this is unnecessary. A table is a fairly static beast, you can use the system view USER_TABLES to determine whether it exists before dropping it.
declare
l_ct number;
begin
-- Determine if the table exists.
select count(*) into l_ct
from user_tables
where table_name = 'THE_TABLE';
-- Drop the table if it exists.
if l_ct = 1 then
execute immediate 'drop table the_table';
end if;
-- Create the new table it either didn-t exist or
-- has been dropped so any exceptions are exceptional.
execute immediate 'create table the_table ( ... )';
end;
/
Using a global temporary table would seem to be a better option. However, if you insist on dropping and re-adding tables at runtime you could query one of the _TABLES views (i.e. USER_TABLES, DBA_TABLES, ALL_TABLES) to determine if the table exists, drop it if it does, then create it:
SELECT COUNT(*)
INTO nCount
FROM USER_TABLES
WHERE TABLE_NAME = 'FOOBAR';
IF nCount <> 0 THEN
EXECUTE IMMEDIATE 'DROP TABLE FOOBAR';
END IF;
EXECUTE IMMEDIATE 'CREATE TABLE FOOBAR(...)';
Share and enjoy.