oracle - concatenate in select for drop, create, grant - lost in '''' - sql

I am new to Oracle database, got a task to write several selects, but I do not get somethow principle, how it works (or better to say does not work). Could you please help me to find a mistake and probably you have a link to some info or converter that helps such writings.
v_sql := 'SELECT ''DROP TABLE ''||object_name||'' as
select *
FROM all_objects
WHERE object_name LIKE '''%''|| v_date ||''%'''
and object_type = ''TABLE''
and owner =''||v_owner||''';

Are you trying to generate DROP statements for a specific user? Start with the below anonymous block and add to it.
--Generate DROP statements for all tables for a user.
declare
v_owner varchar2(128) := user;
begin
for objects in
(
select distinct 'DROP TABLE "'||owner||'"."'||object_name||'"' v_sql
from all_objects
where object_type = 'TABLE'
and owner = v_owner
order by v_sql
) loop
dbms_output.put_line(objects.v_sql);
end loop;
end;
/

Related

How to find to which schema or procedure, table and column a particular value belongs to?

I have a 9 digit number, say "234234234", is there a way to find or check its appearance in my database, like in which particular schema or procedure does it fall? and list out all the tables and columns which has that value in pl/sql developer
This query only searches in stored objects that user is allowed to access (procedure, function, package, ...). You could refer to this
Not sure if there is one way to search for that value in all database table.
SELECT *
FROM all_source
WHERE text LIKE '%234234234%';
--AND owner = 'SCHEMA_NAME';
The below block identifies the given string's presence across all the tables in your DB.
declare
num_rows number;
sql_text varchar2(250);
sql_info varchar2(100);
begin
dbms_output.enable(1000000);
for x in (select table_name, column_name from dba_tab_columns
where data_type in ('VARCHAR','VARCHAR2','CHAR')
and owner <> 'SYSTEM')
loop
sql_text:='select count(*) into :num_rows from SYSTEM.'||x.table_name||' where '||x.column_name||' like ''%234234234%''';
-- dbms_output.put_line (sql_text);
execute immediate sql_text into num_rows;
if num_rows>0
then
sql_info:='Table: '||x.table_name||' contains the string';
dbms_output.put_line (sql_info);
end if;
end loop;
end;
/

Creating a table if it doesn't exist already

I'm trying to create a table if it doesn't exist already. I'm currently checking to see if it exists in DBA_TABLES first and if that query returns nothing then insert. Is there a way to just check in the same statement so I don't have to break it up into separate queries?
This is what I have currently.
BEGIN
SELECT COUNT(*)
INTO lvnTableExists
FROM DBA_TABLES
WHERE Table_Name = 'SOME_TABLE';
IF lvnTableExists = 0 THEN
EXECUTE IMMEDIATE 'CREATE TABLE SOME_TABLE AS (SELECT * FR0M OTHER_TABLE)';
END IF;
END;
This is something that I'm going for.
DECLARE
sql VARCHAR2(100000);
BEGIN
sql := 'CREATE TABLE SOME_TABLE ' ||
'AS (SELECT * FROM OTHER_TABLE) ' ||
'WHERE NOT EXISTS (SELECT NULL ' ||
'FROM DBA_OBJECTS d WHERE d.Object_Name = 'SOME_TABLE' AND ' ||
'd.Owner = 'SOME_TABLE')';
EXECUTE IMMEDIATE sql;
END;
The problem is that, you can't put a WHERE NOT EXISTS in a CREATE TABLE AS statement.
Yes, that's really a shame that Oracle doesn't have that functionality. I'm sure it will come some day. Until then, if you want to write a PL/SQL wrapper, why not do it like that:
DEClARE
table_exists_already exception;
pragma exception_init(table_exists_already, -955 );
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE SOMETABLE...';
EXCEPTION WHEN table_exists_already THEN
DBMS_OUTPUT.PUT_LINE('Table sometable already exists');
END;
/

Get max(length(column)) for all columns in an Oracle table

I need to get the maximum length of data per each column in a bunch of tables. I'm okay with doing each table individually but I'm looking for a way to loop through all the columns in a table at least.
I'm currently using the below query to get max of each column-
select max(length(exampleColumnName))
from exampleSchema.exampleTableName;
I'm basically replacing the exampleColumnName with each column in a table.
I've already went through 3-4 threads but none of them were working for me either because they weren't for Oracle or they had more details that I required (and I couldn't pick the part I needed).
I'd prefer to have it in SQL than in PLSQL as I don't have any create privileges and won't be able to create any PLSQL objects.
Got the below query to work -
DECLARE
max_length INTEGER; --Declare a variable to store max length in.
v_owner VARCHAR2(255) :='exampleSchema'; -- Type the owner of the tables you are looking at
BEGIN
-- loop through column names in all_tab_columns for a given table
FOR t IN (SELECT table_name, column_name FROM all_tab_cols where owner=v_owner and table_name = 'exampleTableName') LOOP
EXECUTE IMMEDIATE
-- store maximum length of each looped column in max_length variable
'select nvl(max(length('||t.column_name||')),0) FROM '||t.table_name
INTO max_length;
IF max_length >= 0 THEN -- this isn't really necessary but just to ignore empty columns. nvl might work as well
dbms_output.put_line( t.table_name ||' '||t.column_name||' '||max_length ); --print the tableName, columnName and max length
END IF;
END LOOP;
END;
Do let me know if the comments explain it sufficiently, else I'll try to do better. Removing table_name = 'exampleTableName' might loop for all tables as well, but this is okay for me right now.
You can try this; although it uses PL/SQL it will work from within SQL-Plus. It doesn't loop. Hopefully you don't have so many columns that the SELECT query can't fit in 32,767 characters!
SET SERVEROUTPUT ON
DECLARE
v_sql VARCHAR2(32767);
v_result NUMBER;
BEGIN
SELECT 'SELECT GREATEST(' || column_list || ') FROM ' || table_name
INTO v_sql
FROM (
SELECT table_name, LISTAGG('MAX(LENGTH(' || column_name || '))', ',') WITHIN GROUP (ORDER BY NULL) AS column_list
FROM all_tab_columns
WHERE owner = 'EXAMPLE_SCHEMA'
AND table_name = 'EXAMPLE_TABLE'
GROUP BY table_name
);
EXECUTE IMMEDIATE v_sql INTO v_result;
DBMS_OUTPUT.PUT_LINE(v_result);
END;
/

DROP and CREATE index at the same time

We have table owner name and index owner name mismatch. We need to drop the index as well the constraints associated with it and recreate the same in the particular schema to match index owner and table owner name. We have different column count for each index varying from 1 to 4.
I need to create a procedure for dropping n recreating at the same time.
declare
total number(10);
table_name varchar2(255);
index_name varchar2(255);
column_name varchar2(255);
begin
select a.table_name, a.index_name,count(a.column_name) into table_name, index_name,total
from all_ind_columns a, all_indexes b where a.index_name = b.index_name
and b.table_owner = 'SIM'and b.owner like 'TIM'
group by a.table_name,a.index_name
order by a.table_name,a.index_name,count(a.column_name);
select c.column_name into column_name from all_ind_columns c,all_indexes d
where c.index_name=d.index_name
and d.table_owner='SIM' and d.owner like 'TIM';
for i in (select a.table_name, a.index_name,count(a.column_name) from all_ind_columns a, all_indexes b where a.index_name = b.index_name
and b.table_owner = 'SIM'and b.owner like 'TIM'
group by a.table_name,a.index_name
order by a.table_name,a.index_name,count(a.column_name))
loop
If i.count(a.column_name)=1 then
DBMS_OUTPUT.PUT_LINE ('Create index'||index_name|| 'on' ||table_name||'('||Column_name||')');
else total>=2
then
DBMS_OUTPUT.PUT_LINE ('Create index'||index_name|| 'on' ||table_name||'('||Column_name,Column_name||')');
end if;
end loop;
end;
DBMS_METADATA is the official way to regenerate object DDL. It's usually better than manually creating DDL statements. There are hundreds of options for creating indexes, DBMS_METADATA.GET_DDL is the only way to ensure you accurately recreate the object.
declare
v_index_ddl clob;
begin
for indexes_in_wrong_schema in
(
select table_name, index_name
from all_indexes
where table_owner = 'SIM' and owner like 'TIM'
) loop
v_index_ddl := dbms_metadata.get_ddl('INDEX',
indexes_in_wrong_schema.index_name, 'TIM');
--Or replace these with "execute immediate" to run instead of print.
dbms_output.put_line('drop index TIM.'||
indexes_in_wrong_schema.index_name);
dbms_output.put_line(replace(v_index_ddl, '"TIM"', '"SIM"'));
end loop;
end;
/
Privileges
DBMS_METADATA requires you either have the SELECT_CATALOG_ROLE or are executing as the schema owner. Ask a DBA or other privileged user if they can grant you that role. Or convert the above PL/SQL block into a function, install the function on the owner's schema, and then grant execute on new_function to your_user;.

auditing all tables in a schema

I was wondering if there is a way (in Oracle(11g)) to audit all of the tables in a given schema. I have a lot of tables that need to be audited and don't want to have to manually audit each individual tables. Would a cursor be appropriate in this situation? Any advice would be greatly appreciated. Cheers!
Here is the simple cursor I thought might work..
cursor table_names is
SELECT owner, table_name
FROM all_tables
where owner like 'MYSCHEMA%';
begin
for x in table_names
loop
audit_all := 'audit all on table_name';
end loop;
end;
You can use dynamic SQL to generate and execute the audit statements
DECLARE
l_sql_stmt varchar2(1000);
BEGIN
FOR t IN (SELECT owner, table_name
FROM all_tables
WHERE owner like 'MYSCHEMA%')
LOOP
l_sql_stmt := 'AUDIT ALL ON ' || t.owner || '.' || t.table_name;
EXECUTE IMMEDIATE l_sql_stmt;
END LOOP;
END;