I executed the script below and it works:
BEGIN
FOR cur_rec IN (SELECT object_name, object_type
FROM user_objects
WHERE object_type IN
('TABLE',
'VIEW',
'PACKAGE',
'PROCEDURE',
'FUNCTION',
'SEQUENCE'
))
LOOP
BEGIN
IF cur_rec.object_type = 'TABLE'
THEN
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '" CASCADE CONSTRAINTS';
ELSE
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"';
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ( 'FAILED: DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"'
);
END;
END LOOP;
END;
/
But the problem is, after this, I cant grant, create or drop etc. in my database even I'm using a sysdba user.
I am getting the error:
ORA-00604: error occurred at recursive SQL level 1
ORA-00942: table or view does not exist
Please help. Thanks.
One possible cause for the recursive SQL error is triggers. You might have run into this scenario:
you have a trigger that fires for every DDL statement
this trigger tries to insert records into some kind of audit/log table
you audit/log table was dropped by your cleanup script
To get a list of all triggers, you can use
select * from dba_triggers
where trigger_type not in ('BEFORE EACH ROW','AFTER EACH ROW')
(you can exclude row-level triggers because they conceptually belong to the table and would have been automatically dropped when you dropped the table). After you've identified the offending trigger, you can either disable or drop it.
Related
I'm adding partitions to an existing table in an Oracle database by creating an intermediary table and then using DBMS_REDEFINITION api to copy dependents from the original table.
CREATE TABLE my_schema.interm_tb AS SELECT * FROM my_schema.original_tb WHERE 1 = 0;
-- add partitions on my_schema.interm_tb
When running the script bellow I am getting num_errors > 0. However, select object_name, base_table_name, ddl_txt from DBA_REDEFINITION_ERRORS; doesn't find any error details. How can I see the error details? I am running as SYS user if it matters.
DECLARE
num_errors PLS_INTEGER;
BEGIN
DBMS_REDEFINITION.start_redef_table('my_schema', 'original_tb', 'interm_tb');
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('my_schema', 'original_tb', 'interm_tb',
DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE,
num_errors);
DBMS_OUTPUT.put_line('num_errors=' || num_errors);
END;
Edit 1:
With ignore_errors set to false I get:
DECLARE
*
ERROR at line 1:
ORA-01442: column to be modified to NOT NULL is already NOT NULL
ORA-06512: at "SYS.DBMS_REDEFINITION", line 2304
So I tried to get all not null constraints on the intermediary table and drop them by adding this block before calling DBMS_REDEFINITION.start_redef_table - this fixed the errors:
FOR q IN (
select 'alter table "' || owner || '"."' || table_name || '" DROP CONSTRAINT "' || CONSTRAINT_NAME || '"' as sql_text
from dba_constraints where table_name='interm_tb'
)
LOOP
DBMS_OUTPUT.put_line(q.sql_text);
EXECUTE IMMEDIATE q.sql_text;
END LOOP;
I created procedure in oracle that drops my table and creates same table from my view. But I have some problems with running this procedure. First step with drop table works but copying it doesn't work.
It this a good procedure ?
create or replace PROCEDURE transfer_table (table_name IN VARCHAR2,tableFrom IN VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
EXECUTE IMMEDIATE 'CREATE TABLE ' || table_name || ' AS SELECT * FROM ' || tableFrom;
commit;
END transfer_table;
Next I click on this procedure and change the variable then view and click ok, but only the first step of dropping the table is working. What am I doing wrong ?
I think you need to catch the error if the table you are creating doesn't exist.
create or replace PROCEDURE transfer_table (table_name IN VARCHAR2,tableFrom IN VARCHAR2) IS
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
EXCEPTION WHEN OTHERS THEN
NULL;
END;
EXECUTE IMMEDIATE 'CREATE TABLE ' || table_name || ' AS SELECT * FROM ' || tableFrom;
commit;
END transfer_table;
I have a database for an application and several environment (development, test and production). I would like to use the option Database copy from SQL Developer in order to retrieve data from the production and copy them in development. Thus data on both environments will be the same.
With a previous version of the program all was working perfectly. Nevertheless with a new version (SQL Developer 18.2) imposed by our company, I obtain several error with different objects like sequences, existing table, primary key, ...) during the copy.
Thus I would like to use a script for cleaning the objects of the Database before to use the tool in order to see if the problem will be solved. But I don't know how to do that.
I found and updated this script:
BEGIN
FOR cur_rec IN (SELECT object_name, object_type
FROM user_objects
WHERE object_type IN
('TABLE',
'VIEW',
'PACKAGE',
'PROCEDURE',
'FUNCTION',
'SEQUENCE',
'SYNONYM'
))
LOOP
BEGIN
IF cur_rec.object_type = 'TABLE'
THEN
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '" CASCADE CONSTRAINTS';
ELSE
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"';
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ( 'FAILED: DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"'
);
END;
END LOOP;
END;
Nevertheless this script Cleanup the Schema by DROPPING all objects. I would like to keep the structure and the objects but just empty the conten.
Could you please help me how to do for cleaning the different object without deleting them and importing again?
Thank in advance for your help.
Sebastien
Is it possible to execute a ALTER INDEX prepared by doing a SELECT on sys tables in Oracle 12c. Please see below
I am trying to find the unused indexes for which I have prepared the alter statements by select clause below -
SELECT 'alter index ' || owner || '.' || index_name || ' monitoring usage;'
FROM dba_indexes
WHERE owner NOT in (
'SYSTEM',
'SYS');
Next, I will have to manually copy the output of this SQL to a new SQL commander tab and execute them. Rather is it possible to execute these statements directly instead of showing them?
I am trying to achieve this in SQL only, as a single statement executable from any SQL utility like DBViz or SQL+, and NOT IN PL/SQL or Unix.
You can do this two ways:
1- Spoofing the result to a file and running the file.
set pages 0 lines 200 feed off term off
spool _file
SELECT 'alter index ' || owner || '.' || index_name || ' monitoring usage;'
FROM dba_indexes
WHERE owner NOT in ('SYSTEM','SYS');
spool off
#_file
1- Or via PL/SQL
BEGIN
FOR rec in (select owner, index_name FROM dba_indexes WHERE owner NOT in ('SYSTEM','SYS'))
LOOP
query := 'alter index ' || rec.owner || '.' || rec.index_name || ' monitoring usage'
execute immediate query;
END LOOP;
end;
/
SELECT * FROM(SELECT 'alter index ' || owner || '.' || index_name || ' monitoring usage;'
FROM dba_indexes
WHERE owner NOT in (
'SYSTEM',
'SYS');)
We have certain environments that prefer the use of materialized views, but the regular applications use regular views. To make things easier we want our application to automatically migrate all the regular views to materialized views in an automated fashion, based upon a configuration parameter.
I've written what I consider to be the most of what I need to get this script working, but I am struggling on the final touches. Possibly there are some escaping issues that I need to work around too.
For now the script creates a view called 'magic' and then tries to convert that, but so far it's not working on the conversion to a materialized view stage. I am unsure what I've done wrong. Any help greatly appreciated.
The error I am seeing is as follows.
Error report:
ORA-00911: invalid character
ORA-06512: at line 49
ORA-00911: invalid character
00911. 00000 - "invalid character"
*Cause: identifiers may not start with any ASCII character other than
letters and numbers. $#_ are also allowed after the first
character. Identifiers enclosed by doublequotes may contain
any character other than a doublequote. Alternative quotes
(q'#...#') cannot use spaces, tabs, or carriage returns as
delimiters. For all other contexts, consult the SQL Language
Reference Manual.
*Action:
Attempting to drop materialized view named MAGIC
No materialized view found with name MAGIC
Attempting to drop view named MAGIC
Success.
Attempting to create materialized view named MAGIC
CREATE MATERIALIZED VIEW "MYDB"."MAGIC" ("MAGIC") AS
SELECT 'MAGIC' FROM DUAL;
Failed to create materialized view, recreating original view MAGIC
ERROR: Could not recreate view named MAGIC.
SQL was:
CREATE OR REPLACE FORCE VIEW "MYDB"."MAGIC" ("MAGIC") AS
SELECT 'MAGIC' FROM DUAL;
The PL/SQL code is below.
clear;
SET serveroutput ON size 1000000;
/**
* Converts all views in the database to materialized views.
*/
CREATE OR REPLACE VIEW "MAGIC" ("MAGIC") AS SELECT 'MAGIC' FROM DUAL;
BEGIN
FOR cur_rec IN ( SELECT object_name, object_type FROM user_objects WHERE object_type='VIEW' and object_name='MAGIC' )
LOOP
BEGIN
FOR cur_view IN
(SELECT TRIM( REPLACE( REPLACE( DBMS_METADATA.GET_DDL('VIEW', cur_rec.object_name), 'CREATE OR REPLACE FORCE VIEW', 'CREATE MATERIALIZED VIEW' ), 'CREATE OR REPLACE VIEW', 'CREATE MATERIALIZED VIEW' ) ) "MATERIALIZED_VIEW",
TRIM( DBMS_METADATA.GET_DDL('VIEW', cur_rec.object_name) ) "VIEW"
FROM DUAL
)
LOOP
BEGIN
BEGIN
DBMS_OUTPUT.PUT_LINE( 'Attempting to drop materialized view named ' || cur_rec.object_name );
EXECUTE IMMEDIATE 'drop materialized view ' || cur_rec.object_name;
DBMS_OUTPUT.PUT_LINE( 'Success.' );
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE( 'No materialized view found with name ' || cur_rec.object_name );
IF SQLCODE != -12003 THEN
RAISE;
END IF;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE( 'Attempting to drop view named ' || cur_rec.object_name );
EXECUTE IMMEDIATE 'drop view ' || cur_rec.object_name;
DBMS_OUTPUT.PUT_LINE( 'Success.' );
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE( 'No view found with name ' || cur_rec.object_name );
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
-- create the view as a materialized view.
BEGIN
DBMS_OUTPUT.PUT_LINE( 'Attempting to create materialized view named ' || cur_rec.object_name );
DBMS_OUTPUT.PUT_LINE( cur_view."MATERIALIZED_VIEW" );
EXECUTE IMMEDIATE cur_view."MATERIALIZED_VIEW";
DBMS_OUTPUT.PUT_LINE( 'Success.' );
EXCEPTION
WHEN OTHERS THEN
BEGIN
DBMS_OUTPUT.PUT_LINE( 'Failed to create materialized view, recreating original view ' || cur_rec.object_name );
EXECUTE IMMEDIATE cur_view."VIEW";
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE( 'ERROR: Could not recreate view named ' || cur_rec.object_name || '.' );
DBMS_OUTPUT.PUT_LINE( 'SQL was:' || cur_view."VIEW" );
RAISE;
END;
END;
END;
END LOOP;
END;
END LOOP;
END;
The problem is with the SQL it's trying to execute:
CREATE MATERIALIZED VIEW "MYDB"."MAGIC" ("MAGIC") AS
SELECT 'MAGIC' FROM DUAL;
The dynamic SQL should be a single statement and cannot have a statement terminator/separator; it's the final ; it doesn't like.
You can stop dbms_metadata including it in the DDL in the first place by adding a call to the set_transform_param() procedure in your block, before you call get_ddl():
dbms_metadata.set_transform_param(dbms_metadata.session_transform,
'SQLTERMINATOR', false);
UPDATE - Final Solution
The database was crashing server-side when running this script as some of my views depend on others. I get the impression that this is done in a multi-threaded fashion and that caused the server to crash and burn as views were in various states of readiness. From a sequential processing point of view, I can't see how this can fail. The dependant views exist either as a materialized view or a regular view.
Finally, it's possible these times could be reduced, these were the values that worked for me, but I've not tested lower thresholds at the time of writing this answer.
set serveroutput on size 1000000;
/**
* Converts all views in the database to materialized views.
*/
begin
dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'SQLTERMINATOR', false );
for cur_rec in ( SELECT object_name, object_type from user_objects where object_type='VIEW' )
loop
begin
for cur_view in
(select trim( replace( replace( dbms_metadata.get_ddl( 'VIEW', cur_rec.object_name ), 'CREATE OR REPLACE FORCE VIEW', 'CREATE MATERIALIZED VIEW' ), 'CREATE OR REPLACE VIEW', 'CREATE MATERIALIZED VIEW' ) ) "MATERIALIZED_VIEW",
trim( dbms_metadata.get_ddl( 'VIEW', cur_rec.object_name ) ) "VIEW"
from dual )
loop
begin
begin
execute immediate 'drop materialized view ' || cur_rec.object_name;
dbms_lock.sleep(5);
exception
when others then
if sqlcode != -12003 then
raise;
end if;
end;
begin
execute immediate 'drop view ' || cur_rec.object_name;
dbms_lock.sleep(5);
exception
when others then
if sqlcode != -942 then
raise;
end if;
end;
-- create the view as a materialized view.
begin
dbms_output.put_line( 'Attempting to create materialized view named ' || cur_rec.object_name );
execute immediate cur_view."MATERIALIZED_VIEW";
dbms_lock.sleep(5);
exception
when others then
begin
dbms_output.put_line( 'Failed to create materialized view, recreating original view ' || cur_rec.object_name );
dbms_output.put_line( 'Error was: ' || sqlerrm( sqlcode ) );
dbms_output.put_line( cur_view."MATERIALIZED_VIEW" );
execute immediate cur_view."VIEW";
dbms_lock.sleep(5);
exception
when others then
dbms_output.put_line( 'ERROR: Could not recreate view named ' || cur_rec.object_name || '.' );
dbms_output.put_line( 'SQL was:' || cur_view."VIEW" );
raise;
end;
end;
end;
end loop;
end;
end loop;
end;