Retrieve Oracle Metadata with Internal Data - sql

I am trying to write a PL/SL Procedure which uses both meta data and internal data of a table.It is like:
table1 (ABC varchar2(50),wsx varchar2(50));
table2 (ABC number(50),dv varchar2(50));
table3 (ABC varchar2(10),wsds varchar2(50));
table4 (ABC varchar2(20),wfsdg varchar2(50));
table5 (ABC number(50),wsxsfd varchar2(50));
All five tables have one column with same name 'ABC'.
Suppose table1 has 3 rows like
('JOHN.TEDA','avdv'),('MARK.LEE','fesf'),('JOHN.DEA','fwfd') and other table also have any data like this.
Now using column name as an input('ABC') i should get output as
attached.
we can get column info from user_tab_columns.
Max length means max length of existing data in column ::
select max(length(ABC)) from table1
I am getting problem in joining both
Tables are not referential.

I have tried to replicate the scenario as mentioned by you with the use of PIPELINED function in Oracle. Hope this helps.
CREATE OR REPLACE TYPE fun_obj
IS
OBJECT
(
tab_name VARCHAR2(100),
colname VARCHAR2(100),
datatyp VARCHAR2(100),
datlen NUMBER,
nullable VARCHAR2(1),
LEN NUMBER );
/
CREATE OR REPLACE
FUNCTION test_max_count(
colname IN VARCHAR2)
RETURN fun_tab PIPELINED
AS
tab fun_obj:=fun_obj(NULL,NULL,NULL,NULL,NULL,NULL);
lvlen NUMBER;
BEGIN
FOR I IN
(SELECT DISTINCT table_name,
OWNER,
COLUMN_NAME,
DATA_TYPE,
DATA_LENGTH,
NULLABLE,
NULL AS MAX_LEN
FROM all_tab_columns
WHERE column_name = colname
)
LOOP
tab.tab_name:=i.table_name;
tab.colname :=i.COLUMN_NAME;
tab.datatyp :=i.DATA_TYPE;
tab.datlen :=i.DATA_LENGTH;
tab.nullable:=i.NULLABLE;
EXECUTE IMMEDIATE 'SELECT MAX(LENGTH('||i.column_name||')) FROM '||I.OWNER||'.'||I.TABLE_NAME INTO lvlen;
tab.len:=lvlen;
PIPE ROW(tab);
END LOOP;
END;
/
------------------------------------To Execute----------------------------------
SELECT * FROM TABLE(test_max_count('abc'));

CREATE OR REPLACE PROCEDURE test2 ( p_column_name IN varchar )
IS
CURSOR GET_DATA (COL VARCHAR )IS
SELECT TABLE_NAME ,COLUMN_NAME,DATA_TYPE,DATA_LENGTH,NULLABLE
FROM
user_tab_columns where COLUMN_NAME = COL;
a_table varchar2(50);
B_COL varchar2(50);
a_max varchar2(50);
BEGIN
FOR C IN GET_DATA(p_column_name) LOOP
a_table := c.table_name;
B_COL := C.COLUMN_NAME;
EXECUTE IMMEDIATE 'SELECT MAX(LENGTH('||B_COL||')) FROM '||a_table into a_max ;
insert into received_Data values (c.table_name,C.COLUMN_NAME,C.DATA_TYPE,C.DATA_LENGTH,C.NULLABLE,a_max);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR (-20001,
p_column_name || ':$:' || SQLERRM, TRUE) ;
END test2;
/
CREATE TABLE RECEIVED_DATA
( TABLE_NAME VARCHAR2(50 BYTE),
COLUMN_NAME VARCHAR2(50 BYTE),
DATA_TYPE VARCHAR2(50 BYTE),
DATA_LENGTH VARCHAR2(50 BYTE),
IS_NULL VARCHAR2(50 BYTE),
MAX_LENGTH VARCHAR2(50 BYTE));

You cannot achieve this directly with SQL. You need PL/SQL + Execute Immediate to do the job.
create a table with your expected columns
then use for each loop to count the max length on each column.

Related

ORA-06553: PLS-801:Internal Error [55018]

I want to make a function call like SELECT URUN_GETIR('test1') FROM DUAL; but i got ORA-06553: PLS-801: Internal Error [55018].
I tried ORA-06553: PLS-801: internal error [55018] when testing function returning ROWTYPE this like for ex URUN_GETIR('test1').KULUSERNAME but getting same error. It didn't work for me.Thanks in advance.
My db table :
My plsql function code :
create or replace FUNCTION URUN_GETIR(KULADI VARCHAR2)
RETURN URUN%ROWTYPE
AS
URUN_TABLO URUN%ROWTYPE;
BEGIN
SELECT * INTO URUN_TABLO FROM URUN ur WHERE ur.kulusername = KULADI;
RETURN URUN_TABLO;
END;
You can achieve your goal with using table functions. Other than that you can not call directly your function like you wanted. Here is another choice for you Use Stackoverflow Wisely
CREATE TABLE URUN
(
CREATED_BY VARCHAR2 (50 CHAR),
CREATED_DATE DATE,
UPDATED_BY VARCHAR2 (50 CHAR),
KULUSERNAME VARCHAR2 (50 CHAR),
ID NUMBER (10)
);
INSERT INTO URUN (CREATED_BY, CREATED_DATE, UPDATED_BY, KULUSERNAME, ID) VALUES('TEST1',TO_DATE('19000101','YYYYMMDD') ,'TTEST1','USER1',1);COMMIT;
INSERT INTO URUN (CREATED_BY, CREATED_DATE, UPDATED_BY, KULUSERNAME, ID) VALUES('TEST2',TO_DATE('19000102','YYYYMMDD') ,'TTEST2','USER2',2);COMMIT;
INSERT INTO URUN (CREATED_BY, CREATED_DATE, UPDATED_BY, KULUSERNAME, ID) VALUES('TEST3',TO_DATE('19000103','YYYYMMDD') ,'TTEST3','USER3',3);COMMIT;
INSERT INTO URUN (CREATED_BY, CREATED_DATE, UPDATED_BY, KULUSERNAME, ID) VALUES('TEST4',TO_DATE('19000104','YYYYMMDD') ,'TTEST4','USER4',4);COMMIT;
CREATE OR REPLACE TYPE URUN_OBJ AS OBJECT
(
CREATED_BY VARCHAR2 (50 CHAR),
CREATED_DATE DATE,
UPDATED_BY VARCHAR2 (50 CHAR),
KULUSERNAME VARCHAR2 (50 CHAR),
ID NUMBER (10)
);
CREATE OR REPLACE TYPE URUN_OBJ_TAB AS TABLE OF URUN_OBJ;
CREATE OR REPLACE FUNCTION URUN_GETIR (KULADI IN VARCHAR2)
RETURN URUN_OBJ_TAB
PIPELINED
AS
REC_OBJ URUN_OBJ;
CURSOR DATA
IS
SELECT *
FROM URUN UR
WHERE UR.KULUSERNAME = KULADI;
BEGIN
FOR REC IN DATA
LOOP
REC_OBJ :=
URUN_OBJ (REC.CREATED_BY,
REC.CREATED_DATE,
REC.UPDATED_BY,
REC.KULUSERNAME,
REC.ID);
PIPE ROW (REC_OBJ);
END LOOP;
RETURN;
END;
/
SELECT * FROM TABLE(URUN_GETIR('USER1'));
CREATED_BY CREATED_DATE UPDATED_BY KULUSERNAME ID
TEST1 1.01.1900 TTEST1 USER1 1

Procedure to Insert into table and its columns by given parameters?

i`ll start this with some code...
CREATE OR REPLACE PROCEDURE LOAD_IMAGE_INTO_TABLE (
imgDir varchar2
, imgName varchar2
, destTable varchar2
, destIndex varchar2
, destBlob varchar2)
AS
fHnd bfile;
b blob;
srcOffset integer := 1;
dstOffset integer := 1;
BEGIN
dbms_lob.CreateTemporary( b, true );
fHnd := BFilename( imgDir, imgName );
dbms_lob.FileOpen( fHnd, DBMS_LOB.FILE_READONLY );
dbms_lob.LoadFromFile( b, fHnd, DBMS_LOB.LOBMAXSIZE, dstOffset, srcOffset );
--insert into (Select * From user_tables Where table_name = destTable) values(imgName,b);
--insert into destTable (destIndex, destBlob) values( imgName, b );
commit;
dbms_lob.FileClose( fHnd );
END LOAD_IMAGE_INTO_TABLE;
As you might see, I am trying to create a procedure which puts an image into a table. Target table name and column names (for imgname and blobfile) will be given as parameters.
Both ways I tried didn't work. (see --insert(...) in code)
Maybe you have any idea how to solve this?
Thanks in advance.

Oracle: dynamic SQL statement based on a mapping table

Take the following statements in order to create the context in this page:
BEGIN TRANSACTION;
CREATE TABLE TABLEA (COLUMN_A VARCHAR2(30));
CREATE TABLE TABLEB (COLUMN_B VARCHAR2(30));
CREATE TABLE MAPPING_TABLE (TABLEA_COL VARCHAR2(30), TABLEB_COL VARCHAR2(30));
INSERT INTO MAPPING_TABLE (TABLEA_COL, TABLEB_COL) VALUES ('COLUMN_A', 'COLUMN_B');
COMMIT;
I want to make a select from TABLEB using the mapping value setted in the MAPPING_TABLE.
In other words, knowing the name of the column of the TABLEA (for example 'COLUMN_A'), I want to make a SELECT directly in the TABLEB.
Something like:
SELECT /*a statement to recover the COLUMN_B based on the 'COLUMN_A' value*/
FROM TABLEB
It is possible to do in SQL statement, or I'm forced to use PL/SQL context (with procedures, etc...)?
Try this,
declare
v_col varchar(30);
v_val varchar(30);
sql_stmt varchar(255);
begin
select tableb_col into v_col
from mapping_table
where tablea_col = 'COLUMN_A';
sql_stmt := 'select '||v_col||' from tableb';
dbms_output.put_line ( sql_stmt ) ;
execute immediate sql_stmt into l_val;
dbms_output.put_line ( v_val) ;
end;

How to select into varray in Oracle

I'm trying to save a set of ids in array:
create or replace type vrray_4 as varray(4) of varchar2(10);
create or replace procedure get_acl_owner_exchange (id in varchar2 ) is
path_count int;
acl_type out vrray_4;
begin
select owner_id into acl_type from kmc_acl_perm
where permission_name = 'read.'
or permission_name = 'write.'
or permission_name = 'delete.';
end get_acl_owner_exchange;
I'm getting the error:
LINE/COL ERROR
-------- --------------------------------------------------------------------------------
3/17 PLS-00103: Encountered the symbol "VRRAY_4" when expecting one of the following:
:= . ( # % ; not null range default character
The symbol ":=" was substituted for "VRRAY_4" to continue.
You have the OUT parameter in the wrong place and you need to use BULK COLLECT INTO rather than just INTO:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE KMC_ACL_PERM(
owner_id VARCHAR2(10),
permission_name VARCHAR2(10)
)
/
CREATE OR REPLACE TYPE vrray_4 AS VARRAY(4) OF VARCHAR2(10)
/
create or replace PROCEDURE GET_ACL_OWNER_EXCHANGE (
id IN VARCHAR2,
acl_type OUT VRRAY_4
) IS
BEGIN
SELECT owner_id
bulk collect into acl_type
from KMC_ACL_PERM
where permission_name IN ( 'read.', 'write.', 'delete.' );
END GET_ACL_OWNER_EXCHANGE;
/
Does this work for you:
CREATE OR REPLACE TYPE vrray_4 AS VARRAY(4) OF VARCHAR2(10);
/
CREATE TABLE kmc_acl_perm (
owner_id VARCHAR2(10),
permission_name VARCHAR2(10)
);
CREATE OR REPLACE PROCEDURE get_acl_owner_exchange (id IN VARCHAR2) IS
path_count NUMBER;
acl_type vrray_4;
BEGIN
SELECT owner_id BULK COLLECT INTO acl_type
FROM kmc_acl_perm
WHERE permission_name IN ('read.', 'write.', 'delete.');
END get_acl_owner_exchange;
/

Workaround for ORA-00997: illegal use of LONG datatype

I want to save some data from a system table user_tab_cols, to a temp table so I can take a dump from it.
There are 100,000 rows in it , I have select from user_tab_cols about 1,000 records and d save them into a temp table with this query:
create table temp table as
select * from user_tab_cols where condition...
I had error 'illegal use of longtype' , because of the column DATA_DEFAULT that contain a type of long.
Is there an alterantive way where I can store a long type into another table?
ORA-00997: illegal use of LONG datatype
It is a restriction on usage of LONG data type. You cannot create an object type with a LONG attribute.
SQL> CREATE TABLE t AS SELECT data_default FROM user_tab_cols;
CREATE TABLE t AS SELECT data_default FROM user_tab_cols
*
ERROR at line 1:
ORA-00997: illegal use of LONG datatype
SQL>
Alternatively, you could use TO_LOB as a workaround. Which would convert it into CLOB data type.
For example,
SQL> CREATE TABLE t AS SELECT TO_LOB(data_default) data_default FROM user_tab_cols;
Table created.
SQL> desc t;
Name Null? Type
----------------------------------------- -------- ----------------------------
DATA_DEFAULT CLOB
SQL>
See more examples of workarounds here.
You'll need to create your target table explicitly, not from select *:
create table demo_copy
( table_name varchar2(30)
, column_name varchar2(30)
, data_type varchar2(106)
, data_type_mod varchar2(3)
, data_type_owner varchar2(30)
, data_length number
, data_precision number
, data_scale number
, nullable varchar2(1)
, column_id number
, default_length number
, data_default clob
, 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)
, hidden_column varchar2(3)
, virtual_column varchar2(3)
, segment_column_id number
, internal_column_id number
, histogram varchar2(15)
, qualified_col_name varchar2(4000) );
(I've made data_default a clob for more convenient querying.)
Then you can insert rows in a PL/SQL loop:
begin
for r in (
select * from user_tab_cols c
where rownum <= 2 -- your filter condition here
)
loop
insert into demo_copy values r;
end loop;
end;
There are some limitations in principle with this approach, as a long column can hold more than the varchar2(32760) that PL/SQL will use in the loop. However, I expect 32K will be enough for most column default expressions.