Simplifying a complex SQL query into a simple query - sql

The below query generates a select statement. Instead of generating the select statement I want the query to execute the select statement that is getting generating and also display the TABLE_NAME, COLUMN_NAME, DATA_TYPE and the MAX(COLUMN_SIZE), and group the results by TABLE_NAME and sort the results in descending order based on the max size of the LOB column.
select table_name,
column_name,
data_type,
'select (max(length(' || COLUMN_NAME || '))/(1024)) as "Size in KB" from '
|| owner || '.' || TABLE_NAME ||';' "querytogetlobsize"
from dba_tab_cols
where owner='&SCHEMA'
and data_type in ('CLOB','BLOB','NCLOB');
Could anyone help me with generating the query. Thank you so much for your help in advance!

Dynamic SQL it is.
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2 l_size NUMBER;
3 BEGIN
4 FOR cur_r
5 IN (SELECT table_name,
6 column_name,
7 data_type,
8 'select (max(length('
9 || COLUMN_NAME
10 || '))/(1024)) as "Size in KB" from '
11 || owner
12 || '.'
13 || TABLE_NAME querytogetlobsize
14 FROM all_tab_cols
15 WHERE owner = 'SCOTT'
16 AND data_type IN ('CLOB', 'BLOB', 'NCLOB'))
17 LOOP
18 EXECUTE IMMEDIATE cur_r.querytogetlobsize
19 INTO l_size;
20
21 DBMS_OUTPUT.put_line (
22 RPAD (cur_r.table_name, 20, ' ')
23 || ' - '
24 || RPAD (cur_r.column_name, 20, ' ')
25 || ': '
26 || TO_CHAR (l_size, '999G990D00'));
27 END LOOP;
28 END;
29 /
which results in
DUGOTRAJNO - KRAJ_BLOB : 1.708,98
DUGOTRAJNO - POCETAK_BLOB : 2.596,62
OSOBA - PHOTO : 390,32
OSOBA - FAKSIMIL : 23,18
ZAHTJEV_PUTNI_NA - NALOG_BLOB : 16.286,69
ZAHTJEV_PUTNI_NA - POZIV_BLOB : 25.609,50
PL/SQL procedure successfully completed.
SQL>

Related

Extract table_name, column_name, data_type, data_length and example of value in Oracle DB

I'm facing a strange request at my job regarding the extraction of the structure of a database. In this extraction the requirer needs the table name, the column name, the column type and the maximum length for VARCHAR columns. In addition it was asked if there is the possibility to provide also an example of value.
This is my query, at the moment
SELECT
table_name,
column_name,
data_type,
CASE WHEN (data_type = 'VARCHAR' OR data_type = 'VARCHAR2') THEN TO_CHAR(char_length) ELSE '-' END AS char_length
FROM all_tab_cols
WHERE owner = 'DB_OWNER'
ORDER BY table_name;
Is there a chance to make a similar query adding also an example of a value contained in each column?
Personally I think it is not possible unless using a very complex (and heavy) stored procedure, but probably someone more skilled than me in database administration has a better input.
Thanks in advance
Dynamic SQL is what you need. For example:
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2 l_val VARCHAR2 (20);
3 BEGIN
4 FOR cur_r IN ( SELECT table_name,
5 column_name,
6 data_type,
7 CASE
8 WHEN ( data_type = 'VARCHAR'
9 OR data_type = 'VARCHAR2')
10 THEN
11 TO_CHAR (char_length)
12 ELSE
13 '-'
14 END AS char_length
15 FROM all_tab_cols
16 WHERE owner = 'SCOTT'
17 AND table_name IN ('DEPT', 'EMP')
18 ORDER BY table_name)
19 LOOP
20 EXECUTE IMMEDIATE 'select max('
21 || cur_r.column_name
22 || ') from '
23 || cur_r.table_name
24 INTO l_val;
25
26 DBMS_OUTPUT.put_line (
27 RPAD (cur_r.table_name || '.' || cur_r.column_name, 15, ' ')
28 || ': '
29 || l_val);
30 END LOOP;
31 END;
32 /
DEPT.DEPTNO : 40
DEPT.LOC : NEW YORK
DEPT.DNAME : test
EMP.MGR : 7902
EMP.HIREDATE : 12.01.1983 00:00
EMP.SAL : 5000
EMP.COMM : 1400
EMP.DEPTNO : 30
EMP.ENAME : WARD
EMP.EMPNO : 7934
EMP.JOB : SALESMAN
PL/SQL procedure successfully completed.
SQL>

Is there any method to find all the table in database that has column with specific values eg. EMP_NAME = ABC?

select table_name
from user_tab_columns
where column_name IN ('EMP_NAME');
This query gives around 150 table names. I want to find all the tables that has column "EMP_NAME" = ABC and delete it. How do I fetch all the tables that has value on the column "EMP_NAME" = ABC ?
For example: I'll create emp_temp table and modify one of its rows so that its ENAME column contains LITTLEFOOT - that's what I want to remove.
SQL> create table emp_temp as select * from emp;
Table created.
SQL> update emp_temp set ename = 'LITTLEFOOT' where ename = 'KING';
1 row updated.
Let's do it:
SQL> set serveroutput on
SQL> declare
2 l_str varchar2(500);
3 l_cnt number := 0;
4 begin
5 for cur_r in (select u.table_name, u.column_name
6 from user_tab_columns u, user_tables t
7 where u.table_name = t.table_name
8 and u.column_name = 'ENAME'
9 )
10 loop
11 l_str := 'SELECT COUNT(*) FROM ' || cur_r.table_name ||
12 ' WHERE ' || cur_r.column_name || ' = ''LITTLEFOOT''';
13
14 execute immediate (l_str) into l_cnt;
15
16 if l_cnt > 0 then
17 dbms_output.put_line(l_cnt ||' : ' || cur_r.table_name);
18 execute immediate 'delete from ' || cur_r.table_name ||
19 ' where ' ||cur_r.column_name || ' = ''LITTLEFOOT''';
20 end if;
21 end loop;
22 end;
23 /
1 : EMP_TEMP
PL/SQL procedure successfully completed.
SQL> select * From emp_temp where ename = 'LITTLEFOOT';
no rows selected
SQL>
Apparently, I've been deleted. Terminated. But I'll be back.
You may loop over all tables returned from the query (using the cursor):
select table_name
from user_tab_columns
where column_name IN ('EMP_NAME');
and use execute immediate to perform delete:
execute immediate 'DELETE from ' || table_name || ' where EMP_NAME='''ABC'''
full example:
for i in (
select distinct table_name
from user_tab_columns
where column_name IN ('EMP_NAME')
) LOOP
execute immediate 'DELETE from ' || i.table_name || ' where EMP_NAME='''ABC''';
END LOOP;

Oracle:List all tables in the database with a column_value = '%value%' for a specific date range?

I need to list out all tables in the database where a particular employee made changes to records. I'm looking for a query in oracle to list out all tables where the employee_name column = 'person_name' and for date > 'sample_date'. is this possible ?
As you said - dynamic SQL helps. For example, based on Scott's sample schema, I'm searching for a table that contains both ENAME and HIREDATE columns with desired values (SCOTT and 09.12.1982 (dd.mm.yyyy)).
SQL> set serveroutput on
SQL>
SQL> DECLARE
2 l_str VARCHAR2(500);
3 l_cnt NUMBER := 0;
4 BEGIN
5 FOR cur_r IN (SELECT t.table_name, u1.column_name col1, u2.column_name col2
6 FROM user_tables t join user_tab_columns u1 on u1.table_name = t.table_name
7 join user_tab_columns u2 on u2.table_name = t.table_name
8 WHERE u1.column_name = 'ENAME'
9 AND u2.column_name = 'HIREDATE'
10 )
11 LOOP
12 l_str := 'SELECT COUNT(*) FROM ' || cur_r.table_name ||
13 ' WHERE ' || cur_r.col1 || ' = ''SCOTT''' ||
14 ' AND ' || cur_r.col2 || ' = date ''1982-12-09''';
15
16 EXECUTE IMMEDIATE (l_str) INTO l_cnt;
17
18 IF l_cnt > 0 THEN
19 dbms_output.put_line(l_cnt ||' row(s) in ' || cur_r.table_name);
20 END IF;
21 END LOOP;
22 END;
23 /
1 row(s) in EMP
PL/SQL procedure successfully completed.
SQL>

query to find the value in all the tables of the database

I am searching for a specific value in the table and there are lot of tables, is there a query to find the value in all the tables of the database so that I can quickly find the value without going through each table one by one.
I have already tried
SELECT owner, table_name, column_name FROM all_tab_columns WHERE column_name LIKE '%52871%';
SELECT * from dba_objects WHERE object_name like '%52871%'
You could search for a VALUE in all COLUMNS of all TABLES in an entire SCHEMA using XML SQL:
For example, I want to search for value KING in all columns of all the tables in entire SCOTT schema:
SQL> variable val varchar2(10)
SQL> exec :val := 'KING'
PL/SQL procedure successfully completed.
SQL> SELECT DISTINCT SUBSTR (:val, 1, 11) "Searchword",
2 SUBSTR (table_name, 1, 14) "Table",
3 SUBSTR (column_name, 1, 14) "Column"
4 FROM cols,
5 TABLE (xmlsequence (dbms_xmlgen.getxmltype ('select '
6 || column_name
7 || ' from '
8 || table_name
9 || ' where upper('
10 || column_name
11 || ') like upper(''%'
12 || :val
13 || '%'')' ).extract ('ROWSET/ROW/*') ) ) t
14 ORDER BY "Table"
15 /
Searchword Table Column
----------- -------------- --------------
KING EMP ENAME

Retrieval of Column name in Oracle

how to retrieve a column name based on the value given in i wnat to get the column_name in oracle
like i dont know a cloumn name but i know the column value
i have tried in this way
select column_name from table_name where column_value=XXXXX;
Try like this:
SQL> select table_name,
column_name,
:search_string search_string,
result
from cols,
xmltable(('ora:view("'||table_name||'")/ROW/'||column_name||'[ora:contains(text(),"%'|| :search_string || '%") > 0]')
columns result varchar2(10) path '.'
)
where table_name in ('EMP', 'DEPT')
Source
If you want to do it in plain SQL, then you could use the XML approach.
For example, to search for the value KING in SCOTT schema:
SQL> variable val varchar2(10)
SQL> exec :val := 'KING'
PL/SQL procedure successfully completed.
SQL> SELECT DISTINCT SUBSTR (:val, 1, 11) "Searchword",
2 SUBSTR (table_name, 1, 14) "Table",
3 SUBSTR (column_name, 1, 14) "Column"
4 FROM cols,
5 TABLE (xmlsequence (dbms_xmlgen.getxmltype ('select '
6 || column_name
7 || ' from '
8 || table_name
9 || ' where upper('
10 || column_name
11 || ') like upper(''%'
12 || :val
13 || '%'')' ).extract ('ROWSET/ROW/*') ) ) t
14 ORDER BY "Table"
15 /
Searchword Table Column
----------- -------------- --------------
KING EMP ENAME
SQL>
Read SQL to Search for a VALUE in all COLUMNS of all TABLES in an entire SCHEMA