PL/SQL - Execute immediate loop using parameter and if/then statement - oracle

Within a shell script I am using a pl/sql block to drop certain users using $USER parameter. If another parameter ${DROP_AB} is Y then drop all users from the cursor. How do I drop all users except one specific user ${USER}AB if the parameter passed is N? Please see below and help with suggestions:
BEGIN
DECLARE
CURSOR c1 IS
SELECT username FROM dba_users WHERE username LIKE '${USER}%';
BEGIN
FOR user_rec IN c1
IF ${DROP_AB}='Y' THEN
LOOP
EXECUTE IMMEDIATE 'DROP USER ' ||user_rec.username|| ' CASCADE';
ELSIF ${DROP_AB}='N' THEN
LOOP
--DROP ALL USERS EXCEPT FOR USER '${USER}AB'
END LOOP;
END;
END;
/

Untested code but somthing along the lines of the below should work, but as suggested in the comment above this will then error on the system schemas / users.
BEGIN
DECLARE
CURSOR c1 IS
SELECT username FROM dba_users WHERE username LIKE '${USER}%';
BEGIN
FOR user_rec IN c1 loop
IF ${DROP_AB}='Y' THEN
EXECUTE IMMEDIATE 'DROP USER ' ||user_rec.username|| ' CASCADE';
ELSE
IF user_rec.username != ${USER}AB THEN
EXECUTE IMMEDIATE 'DROP USER ' ||user_rec.username|| ' CASCADE';
END IF;
END IF;
END LOOP;
END;
END;
/

Related

Truncate and drop storage in multiple tables in oracle

I wanna action a truncate and drop storage in multiple tables in oracle.
I am using the pl/SQL below :
BEGIN
FOR i IN (select('LOG_'||X.TABLE_ID) AS LogTables from LOGFILE X)
LOOP
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || i.LogTables ;
END LOOP;
END;
My code works perfectly but i wanna add the 'DROP STORAGE' clause.
How shall i Proceed ?
I found the answer :
BEGIN
FOR i IN (select('SDE_LOGPOOL_'||X.TABLE_ID) AS LogPoolTables from SDE_LOGFILE_POOL X)
LOOP
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || i.LogPoolTables || ' DROP STORAGE' ;
END LOOP;
END;

Drop Index , then Insert Statement after that Create back Index, does not work in Procedure

create or replace PROCEDURE INSSEL_TBL_TEST AS
BEGIN
DECLARE
TBL varchar2(50):= 'ESSCSHSTMTBPTEST2';
tblNm varchar2(50);
CURSOR tableIndexList IS
(select ES_INDEX_NM,ES_TBL_NM,ES_CRT_INDEX_STMT,ES_DROP_INDEX_STMT FROM ESSP.ESSINDEXCONF WHERE ES_TBL_NM = TBL);
BEGIN
FOR drpInd in tableIndexList LOOP
EXECUTE IMMEDIATE 'drpInd.ES_DROP_INDEX_STMT';
COMMIT;
END LOOP;
execute immediate ('insert into ESSPREP.' ||UPPER(TBL)|| ' select * from ESSP.' ||UPPER(TBL)|| '#ESSPREPLINKESSP');
FOR drpInd in tableIndexList Loop
execute immediate 'drpInd.ES_CRT_INDEX_STMT';
COMMIT;
END LOOP;
END;
END;
above is my procedure to drop index before insert statement, after that create back the index.But it not work,anyone can help ?
Line
EXECUTE IMMEDIATE 'drpInd.ES_DROP_INDEX_STMT';
is wrong. You're trying to use value from cursor but as a fact you're using string literal. To fix this error just remove quotes:
EXECUTE IMMEDIATE drpInd.ES_DROP_INDEX_STMT;
Also, as #XING said, commit is superfluous here.
Your syntax is not correct. See below:
create or replace PROCEDURE INSSEL_TBL_TEST
AS
TBL varchar2(50):= 'ESSCSHSTMTBPTEST2';
tblNm varchar2(50);
CURSOR tableIndexList IS
(select ES_INDEX_NM,ES_TBL_NM,ES_CRT_INDEX_STMT,ES_DROP_INDEX_STMT FROM ESSP.ESSINDEXCONF WHERE ES_TBL_NM = TBL);
BEGIN
FOR drpInd in tableIndexList LOOP
EXECUTE IMMEDIATE drpInd.ES_DROP_INDEX_STMT;
--COMMIT;-- DROP is a DDL hence no need for COMMIT
END LOOP;
execute immediate 'insert into ESSPREP.' ||UPPER(TBL)|| ' select * from ESSP.' ||UPPER(TBL)|| '#ESSPREPLINKESSP';
FOR drpInd in tableIndexList Loop
execute immediate drpInd.ES_CRT_INDEX_STMT;
END LOOP;
END;

Write a PL/SQL Script that fills a table with the help of a cursor

How do I write a PL / SQL program that creates and fills a table for example let's call the table "TABEMP1", it fills it with data from any other table.
What I have so far;
set serveroutput on
set verify off
DECLARE
Cursor cur_emp IS SELECT * FROM EMP;
v_emp EMP%ROWTYPE;
BEGIN
OPEN cur_emp;
LOOP
FETCH cur_emp INTO v_emp;
EXIT WHEN cur_emp%NOTFOUND;
dbms_output.put_line('Ename: ' || v_emp.ename || ' Empno: ' || v_emp.empno);
END LOOP;
CLOSE cur_emp;
END;
/
No need for a cursor, using Native SQL with EXECUTE IMMEDIATE you can achieve that with flexible features:
DECLARE
lv_src_table_name VARCHAR2(30) := 'EMP';
pi_new_table_name VARCHAR2(30) := 'emp_copy';
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE '||pi_new_table_name||' AS SELECT * FROM '||pi_src_table_name;
END;
/
You can turn that into procedure and pass the two parameters with any original/copy tables names you want
In this case you dont need a PLSQL to achieve. A single SQL statement will be more effective. Hope below snippet helps.
CREATE TABLE TEMP_EMP
AS
SELECT * FROM EMP;

Inserting console output data into a Temp Table from pl/sql

I have the below pl/sql which fetches and prints multiple columns from different tables and prints on console. However for a real time scenario, i need all the data to go into a temporary table. SO that user can do a Select * from the temp table and fetch the data retrieved. Can someone please confirm how can I do that?
SET SERVEROUTPUT ON
Declare
Cursor crsr(companyschema varchar2) is Select Person_Id,Birth_Name from salesdemo.PER_PERSON;
personId number;
bioBirthName varchar2(128);
personalBirthName varchar2(128);
usersSysId varchar2(256);
legalEntity number;
territoryId number;
country varchar2(256);
BEGIN
FOR c_schema IN
(SELECT company_schema
FROM sap.sf_companies c,
sap.sf_feature_map m
WHERE c.company_id = m.company_id
AND m.feature_id = 326
)
LOOP
BEGIN
open crsr(c_schema.company_schema);
if crsr%isopen then
loop
begin
fetch crsr into personId, bioBirthName;
exit when crsr%notfound;
dbms_output.Put_line('Schema '|| c_schema.company_schema);
dbms_output.Put_line('PersonId '|| personId);
dbms_output.Put_line('Bio Birth Name '|| bioBirthName);
execute immediate 'select Birth_Name from '||c_schema.company_schema||'EMP_PERSONAL_INFO_T where person_id = :1' INTO personalBirthName using personId;
dbms_output.Put_line('Personal Birth Name '|| personalBirthName);
execute immediate 'select users_sys_id from '||c_schema.company_schema||'EMP_EMPLOYMENT_INFO where person_id = :1' INTO usersSysId USING personId;
dbms_output.Put_line('UsersSysId '|| usersSysId);
execute immediate 'select company from '||c_schema.company_schema||'EMP_JOB_INFO_T where users_sys_id = :1 ' INTO legalEntity USING usersSysId ;
dbms_output.Put_line('Legal Entity '|| legalEntity);
execute immediate 'select territory_id from '||c_schema.company_schema||'FO_LEGAL_ENTITY_T where internal_code =:1' INTO territoryId USING legalEntity;
dbms_output.Put_line('Territory Id '|| territoryId);
execute immediate 'select territory_name from '||c_schema.company_schema||'Territory where territory_id = :1 ' INTO country USING territoryId;
dbms_output.Put_line('Country '|| country);
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -00942 THEN
CONTINUE;
END IF;
end;
end loop;
end if;
close crsr;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -00942 THEN
CONTINUE;
END IF;
END;
END LOOP;
END;
Inserting console output data into a Temp Table from pl/sql
The output you see on the console is from the DBMS_OUTPUT.PUT_LINE procedure. If you want to insert the same out put into a table to use it for further processing, I would suggest a Global Temporary Table.
The data in a global temporary table is private, such that data inserted by a session can only be accessed by that session. The session-specific rows in a global temporary table can be preserved for the whole session, or just for the current transaction. The ON COMMIT clause indicates that the data should be deleted or preserved at the end of the transaction.
ON COMMIT DELETE ROWS
ON COMMIT PRESERVE ROWS
In your case, create the GTT once, and then in your PL/SQL code, insert the rows into the GTT.
For example,
INSERT INTO company_gtt
VALUES
(c_schema.company_schema, personId, bioBirthName, personalBirthName ....)
See more examples here http://oracle-base.com/articles/misc/temporary-tables.php

Drop Statement inside a PL SQL

is it ok to do a Drop inside a PL SQL.
whats wrong with this SQL
I am trying to drop all users.
The problem is in the drop user username cascase statement
connect sys/abcsds#1.1.1.1 as sysdba
exec dbms_output.enable(1000000);
set serveroutput on
DECLARE
BEGIN
for rec in (select username from dba_users where username LIKE 'S%' AND username NOT LIKE 'SY%') loop
dbms_output.put_line(to_char(rec.username));
dbms_sql.execute('drop user rec.username cascade');
end loop;
END;
.
run;
exit;
You can use DDL in a loop but you'll have to build the string since you can't bind object names.
For example:
DECLARE
l_ddl VARCHAR2(1000);
BEGIN
FOR rec IN (SELECT username
FROM dba_users
WHERE username LIKE 'S%'
AND username NOT LIKE 'SY%') LOOP
l_ddl := 'drop user '|| rec.username ||' cascade';
dbms_output.put_line(l_ddl);
EXECUTE IMMEDIATE (l_ddl);
END LOOP;
END;
Be careful though, DDL is not transactional in Oracle (it performs a commit before and after) and thus you won't be able to rollback any changes.

Resources