get min and max from subquery - oracle

I'm trying to get min and max values from query
SELECT TABLE_NAME , COLUMN_NAME
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME IN ('TABLE_A','TABLE_B')
and DATA_TYPE='NUMBER'
AND (DATA_PRECISION IS NULL OR DATA_SCALE IS NULL)
here what I get so far, but it shows nothing:
BEGIN DBMS_OUTPUT.ENABLE (buffer_size => NULL); END;
declare
l_max number;
begin
for "CUR_R" in
(SELECT TABLE_NAME , COLUMN_NAME
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME IN ('TABLE_A','TABLE_B')
and DATA_TYPE='NUMBER'
AND (DATA_PRECISION IS NULL OR DATA_SCALE IS NULL)
)
loop
execute immediate 'select max(' || "CUR_R"."COLUMN_NAME" ||') from ' || "CUR_R"."TABLE_NAME" into l_max;
dbms_output.put_line("CUR_R"."TABLE_NAME" ||'.'|| "CUR_R"."COLUMN_NAME" ||' -> max value = '|| l_max);
end loop;
end;
maybe i missing something?
also, I'm not an admin, just have grants to select to particular tables
can't create procedure or temp table
I expect result of this structure:
owner
column_name
max_value
min_value
maybe I am missing something?
also, I'm not an admin, just have grants to select to particular tables
can't create procedure or temp table

Dynamic SQL Approach
This query produces the query that gets the minand max for each column (line by line).
The simplest approach for ad Hoc purposed is to run the query, copy the result and execute it. You may of course fetch the result in a CLOBvariable and execute immediate it for repeatable tasks.
SELECT
'select '''||TABLE_NAME||''' TABLE_NAME ,''' || COLUMN_NAME||''' COLUMN_NAME,'|| ' max('|| COLUMN_NAME ||
') max_value,' || ' min('|| COLUMN_NAME ||') min_value from '|| TABLE_NAME ||
case when row_number() over (order by table_name desc, column_name desc) != 1 then ' UNION ALL' end as sql_text
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME IN ('TABLE_A','TABLE_B')
and DATA_TYPE='NUMBER'
AND (DATA_PRECISION IS NULL OR DATA_SCALE IS NULL)
order by table_name, column_name;
Result
select 'TABLE_A' TABLE_NAME ,'X' COLUMN_NAME, max(X) max_value, min(X) min_value from TABLE_A UNION ALL
select 'TABLE_A' TABLE_NAME ,'Y' COLUMN_NAME, max(Y) max_value, min(Y) min_value from TABLE_A UNION ALL
select 'TABLE_B' TABLE_NAME ,'X' COLUMN_NAME, max(X) max_value, min(X) min_value from TABLE_B UNION ALL
select 'TABLE_B' TABLE_NAME ,'Y' COLUMN_NAME, max(Y) max_value, min(Y) min_value from TABLE_B

I guess you should remove (comment) precision and scale conditions in cursor's query.
I used user_tab_columns and tables I have in my schema, but ... that's it, more or less:
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2 l_max NUMBER;
3 BEGIN
4 FOR cur_r IN (SELECT table_name, column_name
5 FROM user_tab_columns
6 WHERE table_name IN ('EMP', 'DEPT')
7 AND data_type = 'NUMBER'
8 -- AND ( data_precision IS NULL
9 -- OR data_scale IS NULL)
10 AND 1 = 1)
11 LOOP
12 EXECUTE IMMEDIATE 'select max('
13 || cur_r.column_name
14 || ') from '
15 || cur_r.table_name
16 INTO l_max;
17
18 DBMS_OUTPUT.put_line (
19 cur_r.table_name
20 || '.'
21 || cur_r.column_name
22 || ' -> max value = '
23 || l_max);
24 END LOOP;
25 END;
26 /
DEPT.DEPTNO -> max value = 40
EMP.EMPNO -> max value = 7934
EMP.MGR -> max value = 7902
EMP.SAL -> max value = 5000
EMP.COMM -> max value = 1400
EMP.DEPTNO -> max value = 30
PL/SQL procedure successfully completed.
SQL>

Your query will only return column values where the data type is NUMBER or NUMBER(*,X). If the data type is NUMBER(X) or NUMBER(X,Y) then the filter on DATA_PRECISION IS NULL OR DATA_SCALE IS NULL will exclude those columns.
For example, given the sample data:
CREATE TABLE table_a (
value1 NUMBER,
value2 NUMBER(*,0),
value3 NUMBER(10),
value4 NUMBER(5,2)
);
INSERT INTO table_a
SELECT LEVEL, 2*LEVEL, 3*LEVEL, 4*LEVEL FROM DUAL CONNECT BY LEVEL <= 5;
CREATE TABLE table_b (
value1 NUMBER,
value2 NUMBER(*,0),
value3 NUMBER(10),
value4 NUMBER(5,2)
);
INSERT INTO table_b
SELECT LEVEL + 5, 2*LEVEL - 2, 3*LEVEL + 3, 1/LEVEL FROM DUAL CONNECT BY LEVEL <= 4;
Then:
DECLARE
l_min number;
l_max number;
BEGIN
DBMS_OUTPUT.ENABLE();
FOR c IN (
SELECT OWNER,
TABLE_NAME,
COLUMN_NAME
FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME IN ('TABLE_A','TABLE_B')
AND DATA_TYPE='NUMBER'
AND (DATA_PRECISION IS NULL OR DATA_SCALE IS NULL)
)
LOOP
EXECUTE IMMEDIATE
'select min("' || c.column_name ||'"),
max("' || c.column_name ||'")
from "' || c.owner || '"."' || c.table_name || '"'
INTO l_min, l_max;
DBMS_OUTPUT.PUT_LINE(
c.owner || '.' || c.table_name ||'.'|| c.column_name
|| ' -> min_value = ' || l_min
|| ', max value = '|| l_max
);
END LOOP;
END;
/
Outputs:
FIDDLE_TNHCDFVJDASVYWAHROPU.TABLE_A.VALUE1 -> min_value = 1, max value = 5
FIDDLE_TNHCDFVJDASVYWAHROPU.TABLE_A.VALUE2 -> min_value = 2, max value = 10
FIDDLE_TNHCDFVJDASVYWAHROPU.TABLE_B.VALUE1 -> min_value = 6, max value = 9
FIDDLE_TNHCDFVJDASVYWAHROPU.TABLE_B.VALUE2 -> min_value = 0, max value = 6
The columns value3 and value4 are excluded as they have both scale and precision specified in their data type.
fiddle

why not query like:
select max(x), min(x)
from t

Related

oracle procedure to list table names and corresponding count

I am stucked with an issue.
I have a table called gd_table_order which contains tablenames.
And i need to get the table_name and count of each table to a target one.
target is a view.
I only gave an example with 2 columns, there are 10 columns like this.So in the procedure we need to enter this as a parameter.
And there will be corresponsding 10 views to be generate. below is a sample of 2 views.
V_CHECK_RECORDS_* is the output view name
Could you please help?
I am not sure what is exact requirement here, But you can use the following approach to fetch the number of records from each table.
SQL> -- This is sample data
SQL> WITH SAMPLE_DATA(TNAME) AS
2 (SELECT 'CUSTOMERS' FROM DUAL UNION ALL
3 SELECT 'INTERVAL_TAB' FROM DUAL)
4 -- Your query starts from here
5 SELECT TABLE_NAME,
6 TO_NUMBER(
7 EXTRACTVALUE( XMLTYPE(
8 DBMS_XMLGEN.GETXML('select count(*) c from ' || U.TABLE_NAME)
9 ), '/ROWSET/ROW/C')) COUNT
10 FROM USER_TABLES U JOIN SAMPLE_DATA S ON S.TNAME = U.TABLE_NAME;
TABLE_NAME COUNT
--------------- ----------
CUSTOMERS 1
INTERVAL_TAB 0
SQL>
-- Update
You can generate the view as follows :
-- UPDATED THIS SECTION
CREATE OR REPLACE VIEW V_CHECK_RECORDS_AUS AS
SELECT TABLE_NAME,
TO_NUMBER(
EXTRACTVALUE( XMLTYPE(
DBMS_XMLGEN.GETXML('select count(*) c from '
|| U.TABLE_NAME || ' WHERE oe_name=''BUL''')
), '/ROWSET/ROW/C')) NUM_ROWS
FROM USER_TAB_COLUMNS U JOIN GD_TABLE_ORDER S ON S.TABLE_NAME_AUS = U.TABLE_NAME
WHERE U.COLUMN_NAME = 'OE_NAME';
In the same way you can generate other views.
-- Further Update
CREATE OR REPLACE VIEW V_CHECK_RECORDS_AUS AS
SELECT TABLE_NAME,
CASE WHEN U.COLUMN_NAME IS NOT NULL THEN TO_NUMBER(
EXTRACTVALUE( XMLTYPE(
DBMS_XMLGEN.GETXML('select count(*) c from '
|| U.TABLE_NAME || ' WHERE ' || U.COLUMN_NAME || '=''BUL''')
), '/ROWSET/ROW/C'))
ELSE 0 END NUM_ROWS
FROM GD_TABLE_ORDER S LEFT JOIN USER_TAB_COLUMNS U
ON S.TABLE_NAME_AUS = U.TABLE_NAME AND U.COLUMN_NAME = 'OE_NAME';

ORA-00904 and ORA-06512 when I try to MAX all columns

create or replace PROCEDURE COMPARAISON_TEST as
begin
declare
cursor c_tab is
select table_name, column_name , data_type
from all_tab_columns;
v_sql VARCHAR2 (32000);
begin
FOR r_tab in c_tab LOOP
v_sql := 'SELECT ' ||
r_tab.table_name || ' TABLE_NAME, ' ||
r_tab.column_name || ' COLUMN_NAME, ' ||
'(SELECT MAX(' || r_tab.column_name || ') FROM ' || r_tab.table_name || ') VALUE ' ||
'FROM DUAL ';
execute immediate v_sql;
end LOOP;
end;
end COMPARAISON_TEST;
ERRORS
ORA-00904: "DUAL" : invalid identifier
ORA-06512: à "ODS.COMPARAISON_TEST", line 20
ORA-06512: à "ODS.COMPARAISON_TEST", line 20
ORA-06512: à line 2
Problem is that you're doing it in the dark.
Always, before actually executing dynamic SQL, display it on the screen so that you'd see the string to be executed.
This is what you did (I added WHERE clause to a cursor, to shorten the output):
SQL> declare
2
3 cursor c_tab is
4 select table_name, column_name , data_type
5 from all_tab_columns
6 where owner = 'SCOTT' and table_name = 'DEPT';
7
8 v_sql VARCHAR2 (32000);
9
10 begin
11
12 FOR r_tab in c_tab LOOP
13 v_sql := 'SELECT ' ||
14 r_tab.table_name || ' TABLE_NAME, ' ||
15 r_tab.column_name || ' COLUMN_NAME, ' ||
16 '(SELECT MAX(' || r_tab.column_name || ') FROM ' || r_tab.table_name || ') VALUE ' ||
17 'FROM DUAL ';
18 dbms_output.put_line(v_sql);
19 --execute immediate v_sql;
20 end LOOP;
21 end;
22 /
SELECT DEPT TABLE_NAME, DEPTNO COLUMN_NAME, (SELECT MAX(DEPTNO) FROM DEPT) VALUE
FROM DUAL
SELECT DEPT TABLE_NAME, DNAME COLUMN_NAME, (SELECT MAX(DNAME) FROM DEPT) VALUE
FROM DUAL
SELECT DEPT TABLE_NAME, LOC COLUMN_NAME, (SELECT MAX(LOC) FROM DEPT) VALUE FROM
DUAL
PL/SQL procedure successfully completed.
SQL>
See all those invalid strings? They can't be executed. In order to make them valid, include table and column names into single quotes, e.g.
SELECT 'DEPT' TABLE_NAME, 'DEPTNO' COLUMN_NAME, (SELECT MAX(DEPTNO) FROM DEPT) VALUE
FROM DUAL;
This is what you might have wanted:
SQL> set serveroutput on
SQL>
SQL> declare
2 cursor c_tab is
3 select table_name, column_name , data_type
4 from user_tab_columns
5 where table_name = 'DEPT';
6 v_sql VARCHAR2 (32000);
7 v_val varchar2(200);
8 begin
9 FOR r_tab in c_tab LOOP
10 v_sql := 'SELECT MAX(' || r_tab.column_name || ') FROM ' ||
11 r_tab.table_name;
12 execute immediate v_sql into v_val;
13 dbms_output.put_line(r_tab.table_name||'.'||r_tab.column_name||': '|| v_val);
14 end LOOP;
15 end;
16 /
DEPT.DEPTNO: 40
DEPT.DNAME: SALES
DEPT.LOC: NEW YORK
PL/SQL procedure successfully completed.
SQL>
If you want to store result into a table, then you'd do something like this:
SQL> create table maxes
2 (table_name varchar2(30),
3 column_name varchar2(30),
4 max_value varchar2(30)
5 );
Table created.
SQL> declare
2 cursor c_tab is
3 select table_name, column_name , data_type
4 from user_tab_columns
5 where table_name = 'DEPT';
6 v_sql VARCHAR2 (32000);
7 v_val varchar2(200);
8 begin
9 FOR r_tab in c_tab LOOP
10 v_sql := 'SELECT MAX(' || r_tab.column_name || ') FROM ' ||
11 r_tab.table_name;
12 execute immediate v_sql into v_val;
13 insert into maxes (table_name, column_name, max_value)
14 values
15 (r_tab.table_name, r_tab.column_name, v_val);
16 end LOOP;
17 end;
18 /
PL/SQL procedure successfully completed.
SQL> select * From maxes;
TABLE_NAME COLUMN_NAME MAX_VALUE
--------------- --------------- ---------------
DEPT DEPTNO 40
DEPT DNAME SALES
DEPT LOC NEW YORK
SQL>
You should double single quotes that you want to appear within the string.
v_sql := 'SELECT ''' ||
r_tab.table_name || ''' TABLE_NAME, ''' ||
r_tab.column_name || ''' COLUMN_NAME, ' ||
'(SELECT MAX(' || r_tab.column_name || ') FROM ' || r_tab.table_name || ') VALUE ' ||
'FROM DUAL ';

Can I use this code in oracle pl/sql developer

I'm trying this code in PL/SQL developer but it's not executing nothing. How can I use this code in order to find all tables which column values contains a specific value?
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 all_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 ''%10305698%''';
-- 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;
/
The below demonstration is to Search for a VALUE in all COLUMNS of all TABLES in an entire SCHEMA:
Search a CHARACTER type
Let's look 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>
Search a NUMERIC type
Let's look for the value 20 in SCOTT schema.
SQL> variable val NUMBER
SQL> exec :val := 20
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
----------- -------------- --------------
20 DEPT DEPTNO
20 EMP DEPTNO
20 EMP HIREDATE
20 SALGRADE HISAL
20 SALGRADE LOSAL
SQL>

Find MAX(PK_COLUMN) and display it with corresponding Table Name

I am having 20 tables ( Each table has a PK and data ), i want to find out what is the current MAX(PK) Value for each table.
I Want the result as follows :
TABLE_NAME MAX_VAL
-------------------- ----------
TABELE_A 114
TABELE_B 55
TABELE_C 14
TABELE_D 866
TABELE_3 4552
is there any way to accomplish this or else i have to write 20 times SELECT MAX(PK_COL) FROM TABLE ?
Assuming your currently connected schema is composed of those twenty tables, and each have identical primary key column name(pk_col), then consider the following code block containing an implicit cursor :
declare
v_max pls_integer;
begin
dbms_output.put_line('table_name max_val');
for c in ( select * from user_tables )
loop
execute immediate 'select max(pk_col) from '||c.table_name into v_max;
dbms_output.put_line(c.table_name||' '||v_max);
end loop;
end;
/
i have found another method which will bring TABLE_NAME,PK_COLUMN and MAX( PK_COLUMN ).
SELECT CASE
WHEN RN = 1 THEN
FORMATTED_QUERY_SET
ELSE
FORMATTED_QUERY_SET || ' UNION ALL '
END AS FORMATTED_QUERY_SET
FROM (SELECT ' SELECT NVL(MAX( ' || COL.COLUMN_NAME ||
' ),0) CURR_MAX_VAL, ''' || TAB.TABLE_NAME ||
''' TABLE_NAME,''' || COL.COLUMN_NAME ||
''' COLUMN_NAME FROM ' || TAB.TABLE_NAME AS FORMATTED_QUERY_SET,
TAB.TABLE_NAME,
ROW_NUMBER() OVER(ORDER BY TAB.TABLE_NAME DESC) AS RN
FROM USER_CONSTRAINTS TAB
JOIN USER_CONS_COLUMNS COL
ON TAB.TABLE_NAME = COL.TABLE_NAME
JOIN USER_TAB_COLUMNS COL2
ON COL.COLUMN_NAME = COL2.COLUMN_NAME
AND COL.TABLE_NAME = COL2.TABLE_NAME
WHERE TAB.CONSTRAINT_TYPE = 'P'
AND COL.CONSTRAINT_NAME LIKE '%_PK'
AND REGEXP_LIKE(COL2.DATA_TYPE, ('NUMB|INTE')))
ORDER BY TABLE_NAME;
Copy the output returned by the above query and execute.
Note : Remove the last ' UNION ALL ' operator from the query string.
Note : Please correct me if i am doing anything wrong .

How do I get column datatype in Oracle with PL-SQL with low privileges?

I have "read only" access to a few tables in an Oracle database. I need to get schema information on some of the columns. I'd like to use something analogous to MS SQL's sp_help.
I see the table I'm interested in listed in this query:
SELECT * FROM ALL_TABLES
When I run this query, Oracle tells me "table not found in schema", and yes the parameters are correct.
SELECT
DBMS_METADATA.GET_DDL('TABLE', 'ITEM_COMMIT_AGG', 'INTAMPS') AS DDL
FROM DUAL;
After using my Oracle universal translator 9000 I've surmised this doesn't work because I don't have sufficient privileges. Given my constraints how can I get the datatype and data length of a column on a table I have read access to with a PL-SQL statement?
ALL_TAB_COLUMNS should be queryable from PL/SQL. DESC is a SQL*Plus command.
SQL> desc all_tab_columns;
Name Null? Type
----------------------------------------- -------- ----------------------------
OWNER NOT NULL VARCHAR2(30)
TABLE_NAME NOT NULL VARCHAR2(30)
COLUMN_NAME NOT NULL VARCHAR2(30)
DATA_TYPE VARCHAR2(106)
DATA_TYPE_MOD VARCHAR2(3)
DATA_TYPE_OWNER VARCHAR2(30)
DATA_LENGTH NOT NULL NUMBER
DATA_PRECISION NUMBER
DATA_SCALE NUMBER
NULLABLE VARCHAR2(1)
COLUMN_ID NUMBER
DEFAULT_LENGTH NUMBER
DATA_DEFAULT LONG
NUM_DISTINCT NUMBER
LOW_VALUE RAW(32)
HIGH_VALUE RAW(32)
DENSITY NUMBER
NUM_NULLS NUMBER
NUM_BUCKETS NUMBER
LAST_ANALYZED DATE
SAMPLE_SIZE NUMBER
CHARACTER_SET_NAME VARCHAR2(44)
CHAR_COL_DECL_LENGTH NUMBER
GLOBAL_STATS VARCHAR2(3)
USER_STATS VARCHAR2(3)
AVG_COL_LEN NUMBER
CHAR_LENGTH NUMBER
CHAR_USED VARCHAR2(1)
V80_FMT_IMAGE VARCHAR2(3)
DATA_UPGRADED VARCHAR2(3)
HISTOGRAM VARCHAR2(15)
You can use the desc command.
desc MY_TABLE
This will give you the column names, whether null is valid, and the datatype (and length if applicable)
The best solution that I've found for such case is
select column_name, data_type||
case
when data_precision is not null and nvl(data_scale,0)>0 then '('||data_precision||','||data_scale||')'
when data_precision is not null and nvl(data_scale,0)=0 then '('||data_precision||')'
when data_precision is null and data_scale is not null then '(*,'||data_scale||')'
when char_length>0 then '('||char_length|| case char_used
when 'B' then ' Byte'
when 'C' then ' Char'
else null
end||')'
end||decode(nullable, 'N', ' NOT NULL')
from user_tab_columns
where table_name = 'TABLE_NAME'
and column_name = 'COLUMN_NAME';
#Aaron Stainback, thank you for correction!
Note: if you are trying to get this information for tables that are in a different SCHEMA use the all_tab_columns view, we have this problem as our Applications use a different SCHEMA for security purposes.
use the following:
EG:
SELECT
data_length
FROM
all_tab_columns
WHERE
upper(table_name) = 'MY_TABLE_NAME' AND upper(column_name) = 'MY_COL_NAME'
select t.data_type
from user_tab_columns t
where t.TABLE_NAME = 'xxx'
and t.COLUMN_NAME='aaa'
Oracle 11.2: Get a list of the full datatype in your table:
create table SOMETABLE (foo integer, bar varchar(300));
select data_type || '(' || data_length || ')' thetype
from user_tab_columns where TABLE_NAME = 'SOMETABLE';
Prints:
NUMBER(22)
VARCHAR(300)
Screenshot:
Documentation:
https://docs.oracle.com/cd/B19306_01/server.102/b14237/statviews_4462.htm#REFRN26277
select column_name, data_type || '(' || data_length || ')' as datatype
from all_tab_columns
where TABLE_NAME = upper('myTableName')
Quick and dirty way (e.g. to see how data is stored in oracle)
SQL> select dump(dummy) dump_dummy, dummy
, dump(10) dump_ten
from dual
DUMP_DUMMY DUMMY DUMP_TEN
---------------- ----- --------------------
Typ=1 Len=1: 88 X Typ=2 Len=2: 193,11
1 row selected.
will show that dummy column in table sys.dual has typ=1 (varchar2), while 10 is Typ=2 (number).
You can try this.
SELECT *
FROM (SELECT column_name,
data_type,
data_type
|| CASE
WHEN data_precision IS NOT NULL
AND NVL (data_scale, 0) > 0
THEN
'(' || data_precision || ',' || data_scale || ')'
WHEN data_precision IS NOT NULL
AND NVL (data_scale, 0) = 0
THEN
'(' || data_precision || ')'
WHEN data_precision IS NULL AND data_scale IS NOT NULL
THEN
'(*,' || data_scale || ')'
WHEN char_length > 0
THEN
'(' || char_length
|| CASE char_used
WHEN 'B' THEN ' Byte'
WHEN 'C' THEN ' Char'
ELSE NULL
END
|| ')'
END
|| DECODE (nullable, 'N', ' NOT NULL')
DataTypeWithLength
FROM user_tab_columns
WHERE table_name = 'CONTRACT')
WHERE DataTypeWithLength = 'CHAR(1 Byte)';
To see the internal representation size in bytes you can use:
REGEXP_SUBSTR(DUMP(your_column_name), 'Len=(\d+)\:', 1, 1, 'c', 1 )
DECLARE
c NUMBER;
d NUMBER;
col_cnt INTEGER;
f BOOLEAN;
rec_tab DBMS_SQL.DESC_TAB;
col_num NUMBER;
PROCEDURE print_rec(rec in DBMS_SQL.DESC_REC) IS
BEGIN
DBMS_OUTPUT.NEW_LINE;
DBMS_OUTPUT.PUT_LINE('col_type = '
|| rec.col_type);
DBMS_OUTPUT.PUT_LINE('col_maxlen = '
|| rec.col_max_len);
DBMS_OUTPUT.PUT_LINE('col_name = '
|| rec.col_name);
DBMS_OUTPUT.PUT_LINE('col_name_len = '
|| rec.col_name_len);
DBMS_OUTPUT.PUT_LINE('col_schema_name = '
|| rec.col_schema_name);
DBMS_OUTPUT.PUT_LINE('col_schema_name_len = '
|| rec.col_schema_name_len);
DBMS_OUTPUT.PUT_LINE('col_precision = '
|| rec.col_precision);
DBMS_OUTPUT.PUT_LINE('col_scale = '
|| rec.col_scale);
DBMS_OUTPUT.PUT('col_null_ok = ');
IF (rec.col_null_ok) THEN
DBMS_OUTPUT.PUT_LINE('true');
ELSE
DBMS_OUTPUT.PUT_LINE('false');
END IF;
END;
BEGIN
c := DBMS_SQL.OPEN_CURSOR;
-- YOUR SELECT HERE
DBMS_SQL.PARSE(c, '
SELECT *
FROM table1 a
bable2 b
table3 c
where a.id = b.id
and b.id2 = c.id
', DBMS_SQL.NATIVE);
d := DBMS_SQL.EXECUTE(c);
DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
col_num := rec_tab.first;
IF (col_num IS NOT NULL) THEN
LOOP
print_rec(rec_tab(col_num));
col_num := rec_tab.next(col_num);
EXIT WHEN (col_num IS NULL);
END LOOP;
END IF;
DBMS_SQL.CLOSE_CURSOR(c);
END;
/

Resources