Drop Statement inside a PL SQL - oracle

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.

Related

how can I write PL/SQL Query for defining role and grant only select access to all schemas for different users

Example includes 2 roles -
READ_ONLY - for select access only
READ_WRITE - for update, insert, delete, drop, etc.
Now I want to fire pl/sql query to -
For loop to get all schema names:
Grant select on BGREADONLY to for User_X;
Please help with the exact piece of code..
you can try this procedure
CREATE or replace PROCEDURE grant_select(
in_var_username VARCHAR2,
in_var_grantee VARCHAR2)
AS
BEGIN
FOR rec IN (
SELECT owner, table_name FROM all_tables WHERE owner = in_var_username
)
LOOP
EXECUTE IMMEDIATE
'GRANT SELECT ON '||rec.owner||'.'||rec.table_name||' TO ' || in_var_grantee || ' with grant option ';
END LOOP;
END;
-- Call the procedure
exec grant_select('OWNER_SCHEMA','ROLE_TO_BE_GRANTED');

Grant a user select, insert, update, delete to a specfic schema

I would like to grant a user i have created the permissions : select, insert, update, delete on a specific schema.
Do I need to be in the schema to do it ? (alter session set current_schema='my_schema';)
Thanks in advance
User often are asking for a single statement to Grant privileges in a single step.
there are multiple workarounds for not have a GRANT SELECT on all table
FOR x IN (SELECT * FROM user_tables)
LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON ' || x.table_name || ' TO <<someone>>';
END LOOP;
or
declare
cursor c1 is select table_name from user_tables;
cmd varchar2(200);
begin
for c in c1 loop
cmd := 'GRANT SELECT ON '||c.table_name|| <<TO YOURUSERNAME>>;
execute immediate cmd;
end loop;
end;
Oracle could implement a schema level grant
GRANT SELECT ON <schema name> to <<user>>

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;

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

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;
/

PL/SQL EXECUTE IMMEDIATE inside LOOP (procedure to truncate all tables in schema)

I need to create procedure which will delete all data from tables in one schema. I try something like that
CREATE OR REPLACE PROCEDURE CLEAR_ALL
IS
sql_truncate VARCHAR2(50);
cursor c1 is
SELECT table_name
FROM all_tables
WHERE owner = 'KARCHUDZ_S';
BEGIN
sql_truncate := 'TRUNCATE TABLE :text_string';
FOR table_name in c1
LOOP
EXECUTE IMMEDIATE sql_truncate USING table_name;
END LOOP;
END CLEAR_ALL;
But it gives me two errors which i cannot understand and fix.
Error(13,7): PL/SQL: Statement ignored
Error(13,44): PLS-00457: Statment must be type of SQL <-- (This error
i had to translate, cause i use University Oracle 11g base which have
Polish lang)
Why not just generate the statement and call it, like this?
CREATE OR REPLACE PROCEDURE CLEAR_ALL
IS
vs_statement VARCHAR2(100);
cursor c1 is
SELECT table_name
FROM all_tables
WHERE owner = 'KARCHUDZ_S';
BEGIN
FOR table_rec in c1
LOOP
vs_statement := 'TRUNCATE TABLE ' || table_rec.table_name;
EXECUTE IMMEDIATE vs_statement;
END LOOP;
END CLEAR_ALL;
You can't use bind variables (i.e. your using clause) as a placeholder for an object name. If you could, you wouldn't need to use dynamic SQL in the first place. You'll have to use concatenation or substitution instead:
CREATE OR REPLACE PROCEDURE CLEAR_ALL
IS
sql_truncate CONSTANT VARCHAR2(50) := 'TRUNCATE TABLE [text_string]';
cursor c1 is
SELECT table_name
FROM all_tables
WHERE owner = 'KARCHUDZ_S';
BEGIN
FOR row in c1
LOOP
EXECUTE IMMEDIATE replace(sql_truncate, '[text_string]', row.table_name);
END LOOP;
END CLEAR_ALL;

Resources