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

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>

Related

Simplifying a complex SQL query into a simple query

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>

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>

How to print first 5 rows of all the tables in an oracle database (schema)?

I want to open a database (schema) which holds about 100 tables,
Once it's opened I would like to print the top 5 rows of all the tables along with their column names.
My first step was to try and get the schema and table names in the database.
so this is what I used for that.
SELECT owner, table_name
FROM all_tables
The expected result will contain the table name, column names and top 5 rows of the table.
I am using Oracle SQL Developer ( Oracle database)
You can try this if you're running Oracle 12c and above.
SET SERVEROUTPUT ON
SET FEEDBACK OFF
DECLARE
x SYS_REFCURSOR;
BEGIN
FOR tabs IN ( SELECT rownum as rn,owner,table_name
FROM all_tables where owner='HR'
and ROWNUM < 10
) LOOP
OPEN x FOR 'SELECT '''|| tabs.owner||'.'|| tabs.table_name||'''
as "table" FROM DUAL';
dbms_sql.return_result(x);
OPEN x FOR 'select * from '
|| tabs.owner
||'.'
|| tabs.table_name
|| ' FETCH FIRST 5 ROWS ONLY ';
dbms_sql.return_result(x);
END LOOP;
END;
/
Output
table
----------
HR.REGIONS
REGION_ID REGION_NAME
---------- -------------------------
1 Europe
2 Americas
3 Asia
4 Middle East and Africa
table
------------
HR.LOCATIONS
LOCATION_ID STREET_ADDRESS POSTAL_CODE CITY STATE_PROVINCE CO
----------- ---------------------------------------- ------------ ------------------------------ ------------------------- --
1000 1297 Via Cola di Rie 00989 Roma IT
1100 93091 Calle della Testa 10934 Venice IT
1200 2017 Shinjuku-ku 1689 Tokyo Tokyo Prefecture JP
1300 9450 Kamiya-cho 6823 Hiroshima JP
1400 2014 Jabberwocky Rd 26192 Southlake Texas US
table
--------------
HR.DEPARTMENTS
DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID LOCATION_ID
------------- ------------------------------ ---------- -----------
10 Administration 200 1700
20 Marketing 201 1800
30 Purchasing 114 1700
40 Human Resources 203 2400
50 Shipping 121 1500
Normally we would use dynamic SQL for this sort of thing. But it's messy to handle the output of 100 different tables in PL/SQL. So, you need to generate a script.
Step 1: Run this in SQL Developer.
select 'prompt ' || owner ||'.' || table_name ||chr(10)
||'select * from ' || owner ||'.' || table_name
|| ' where rownum <=5;'
from all_tables
order by owner, table_name;
Step 2: Cut'n'paste the output into a SQL Worksheet. Unless you're luckier than I am you'll need to edit the annoying double quotes at the start and end of each line (a SQL Developer feature caused by the line break, I think).
Step 3: Run the (edited) output as a script and the Script Output pane will give you the results you want.
Is it possible for me to feed the schema(database) name
Add where owner = '&schema_name' after from all_tables. Or just use USER_TABLES if you're interested in the schema to which you're connected.
Following is the code which you are looking for. I have used USER_TAB_COLUMNS view so that only tables owned by your schema in which you are executing the code is considered.
Feel free to format the output according to your need.
SET SERVEROUT ON
DECLARE
LV_QUERY VARCHAR2(32767);
LV_RESULT VARCHAR2(32767);
BEGIN
DBMS_OUTPUT.PUT_LINE('---------------------------------------');
DBMS_OUTPUT.PUT_LINE('---------------------------------------');
FOR I IN (
SELECT
C.TABLE_NAME,
LISTAGG(C.COLUMN_NAME, ' || ''****'' || ') WITHIN GROUP(
ORDER BY
C.COLUMN_ID
) COLS
FROM
USER_TAB_COLUMNS C
GROUP BY
C.TABLE_NAME
ORDER BY
1
) LOOP
LV_QUERY := 'SELECT '
|| q'#RTRIM(XMLAGG(XMLELEMENT(E,VALS,CHR(10)).EXTRACT('//text()') ORDER BY 1).GetClobVal(),CHR(10)) FROM#'
|| '(SELECT '
|| I.COLS
|| ' AS VALS FROM '
|| I.TABLE_NAME
|| ' FETCH FIRST 5 ROWS ONLY)';
BEGIN
-- DBMS_OUTPUT.PUT_LINE(lv_query);
EXECUTE IMMEDIATE LV_QUERY
INTO LV_RESULT;
DBMS_OUTPUT.PUT_LINE(CHR(10));
DBMS_OUTPUT.PUT_LINE('TABLE NAME : ' || I.TABLE_NAME);
DBMS_OUTPUT.PUT_LINE('COLUMN NAMES : '
|| REPLACE(REPLACE(REPLACE(I.COLS, '*', ''), '||', ''), '''', '**'));
DBMS_OUTPUT.PUT_LINE(LV_RESULT);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO DATA IN TABLE : ' || I.TABLE_NAME);
END;
DBMS_OUTPUT.PUT_LINE(CHR(10));
DBMS_OUTPUT.PUT_LINE('---------------------------------------');
DBMS_OUTPUT.PUT_LINE('---------------------------------------');
END LOOP;
END;
Hope this is what you are looking for.

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