How to select from a parameter (cursor,varchar2, etc) - oracle

I have a little problem and if you could help me it would be great.
DECLARE
CURSOR cur1 IS
SELECT table_name
FROM all_tab_columns
WHERE column_name LIKE 'DESCRIPTION';
tableName varchar2(100);
BEGIN
OPEN cur1;
LOOP
FETCH cur1 INTO tableName;
EXIT WHEN cur1%NOTFOUND;
dbms_output.put_line(tablename);
END LOOP;
END;
What I need is to get all the information possible from those tables with the condition:
WEHRE DESCRIPTION LIKE 'Transaction%'
Something like this
SELECT *
FROM tableName ---- from above
WEHRE DESCRIPTION LIKE 'Transaction%'
I would like to select all data from the tables in my cursor.
The tables don't have the same structure, one can have 4 coloumns, one can have 10 coloumns.
Can it be done in an anonymous block?
Can anyone help me, please?

Try this:
DECLARE
CURSOR cur1 IS
SELECT table_name
FROM user_tab_columns
WHERE column_name LIKE 'DESCRIPTION';
tableName varchar2(100);
l_description varchar2(100);
l_str_val varchar2(100) := 'Transaction%';
l_cursor sys_refursor;
BEGIN
OPEN cur1;
LOOP
FETCH cur1 INTO tableName;
EXIT WHEN cur1%NOTFOUND;
open l_cursor for 'select DESCRIPTION from ' || tableName || ' where DESCRIPTION like :description' using l_str_val;
loop
fetch l_cursor into l_description;
exit when l_cursor%NOTFOUND;
dbms_output.put_line(tablename || ' ' || l_description);
end loop;
close l_cursor;
END LOOP;
close cur1;
END;
I extracted only description column, because I am sure this column is in the table, if you want to extract more columns you have to rewrite this like:
WHERE column_name = ('DESCRIPTION', 'ID', NAME)
and then:
execute immediate 'select DESCRIPTION, ID, NAME from ' || tableName || ' where DESCRIPTION like :description' into l_description, l_id, l_name using l_str_val;

Related

Oracle query logic to identify email addresses across the dwh schemas

I was performing an activity to identify eMail addresses based on certain pattern (#xyz.de). I initially tried checking the DBA_TAB_COLS [data dictionary] view but this just finds email column names and I manually need to check the big list of tables. Instead of doing that, is there is a more effective way to just fetch the the pattern value #xyz.de ?
Database - oracle 11g
Query used
SET SERVEROUTPUT ON 100000
DECLARE
lv_count number(10):=0;
l_str varchar2 (1000);
lv_col_name varchar2(255) :='EMAIL';
BEGIN
FOR V1 IN
(select distinct table_name
from dba_tab_columns
where column_name = lv_col_name
order by table_name)
LOOP
dbms_output.put_line(lv_col_name||' '||v1.table_name);
END LOOP;
END;
Please note that
I don't exactly know the table or column names.
The value #xyz.de can be in any schema and any table and any column. This has to be identified but in an effective way.
Any suggestions?
i have used the above block query to fetch the email column along with the table name , but how can i achieve by searching certain value #xyz.de using the dynamic sql ?
I don't know what you want to do with the values that you are trying to extract, so the below code just prints them. Refer to PL/SQL Dynamic SQL from the Oracle documentation.
declare
type EMAILS is ref cursor;
L_CURSOR EMAILS;
cursor EMAIL_COLS is
select OWNER
,TABLE_NAME
,COLUMN_NAME
from DBA_TAB_COLS
where COLUMN_NAME like '%EMAIL%'
and OWNER <> 'SYS';
L_SQL varchar2(200);
L_EMAIL varchar2(500);
begin
for REC in EMAIL_COLS
loop
L_SQL := 'select ' || REC.COLUMN_NAME || ' from ' || REC.OWNER || '.' || REC.TABLE_NAME || ' where ' || REC.COLUMN_NAME || ' like ''%xyz.de''';
open L_CURSOR for L_SQL;
loop
fetch L_CURSOR into L_EMAIL;
exit when L_CURSOR%notfound;
DBMS_OUTPUT.PUT_LINE(L_EMAIL);
end loop;
end loop;
end;

error ORA-00998: must name this expression with a column alias

I tried to create table from all_tab_columns but it throws me an error.
like error ORA-00998: must name this expression with a column alias.
i tried to figure it out but not working.
Declare
CURSOR c1 IS
SELECT COLUMN_NAME FROM (select 'standard_hash(MY_NAME) AS MY_NAME' COLUMN_NAME from DUAL
UNION
SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE TABLE_NAME='TABLE1' AND COLUMN_NAME<>'MY_NAME');
cols c1%ROWTYPE;
sqlstmt VARCHAR2(4000);
BEGIN
OPEN c1;
LOOP
FETCH c1 into cols;
EXIT WHEN c1%NOTFOUND;
sqlstmt := sqlstmt ||cols.column_name||',';
END LOOP;
CLOSE c1;
sqlstmt := 'CREATE TABLE TABLE2 AS SELECT '||substr(sqlstmt, 1, length(sqlstmt)-1)||' FROM TABLE1';
DBMS_OUTPUT.PUT_LINE(sqlstmt);
EXECUTE IMMEDIATE sqlstmt;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error '||sqlerrm);
END;
/
You just have to give the name to the expression as follows:
sqlstmt := 'CREATE TABLE TABLE2 AS SELECT '
||substr(sqlstmt, 1, length(sqlstmt)-1)
||' as column_name FROM TABLE1'; -- column_name will bre name of the column of new table
As it will become the name of the column of newly created table.
I think this can be simplified somewhat.
You don't need to declare an explicit cursor and a record type and fetch each row into it, as this is already built into the language as the Cursor FOR loop construction:
declare
sqlStmt long := 'create table table2 as select ';
begin
for r in (
select 'standard_hash(my_name) as my_name' column_name
from dual
union
select column_name
from all_tab_columns
where table_name = 'TABLE1'
and column_name <> 'MY_NAME'
)
loop
sqlStmt := sqlStmt || r.column_name || ', ';
end loop;
sqlStmt := sqlStmt || rtrim(sqlStmt,', ') || ' from table1';
dbms_output.put_line(sqlStmt);
execute immediate sqlStmt;
end;
/
But you can do this without any loop, as the listagg function can already build a comma-separated list for you. It also makes it easier to retain the order of columns in the original table.
declare
selectList long;
sqlStmt long;
begin
select listagg(
case column_name
when 'MY_NAME' then 'standard_hash(my_name) as my_name'
else lower(column_name)
end, ', '
) within group (order by column_id) as select_list
into selectList
from user_tab_columns c
where c.table_name = 'TABLE1';
sqlStmt :=
'create table table2 pctfree 0 nologging parallel as '||chr(10)||
'select '||selectList||chr(10)||
'from table1';
dbms_output.put_line(sqlStmt||';');
execute immediate sqlstmt;
end;

Oracle, For cicle with a dinamic table

Hy Guys,
i have a problem with a Cursor, i can't find a solution.
i would like to do a second loop like in the code, where i loop dynamically for the table found above but return that error PLS-00103: Encountered the symbol "LOOP".
i am starting with pl-sql.
Can you give me some suggestions for fix that problem?
thx, all.
CURSOR V_LIST_TABLES IS
SELECT
OBJECT_TYPE,
OWNER ||'.'|| OBJECT_NAME AS SCHEMA,
OBJECT_NAME
FROM DBA_OBJECTS U
WHERE OWNER = 'MYSCHEMA'
AND OBJECT_TYPE IN ('TABLE');
BEGIN
FOR INDX_CURSOR IN V_LIST_TABLES LOOP
IF INDX_CURSOR.OBJECT_NAME LIKE '%TEST%' THEN
FOR INDX_CURSOR_2 IN ('SELECT * FROM' || INDX_CURSOR.OBJECT_NAME) LOOP
NULL;
-- DO SOMETHINGS
END LOOP;
END IF;
END LOOP;
You're making this way more complex than it need be.
vsql varchar2(200);
vfname varchar2(20);
vlname varchar2(20);
vdob date;
For x in (select owner,
table_name
from dba_tables
where owner = 'MYSCHEMA'
and table_name like '%TEST%'
)
loop
-- do something with x.owner and x.table_name
vsql := 'select fname, lname, dob into vfname, vlname, vdob from '||
x.owner||'.'||x.table_name;
dbms_output.put_line(vsql); -- debug only
execute vsql;
end loop;

oracle select * from variable table name

ORACLE: So far nothing I have tried has worked. I wish to display on the screen the results of select * from my_table. In this case my_table = select table_name from all_tables where owner='ABC' and name like 'ABC%'. Table name would be a plus, but column name is a necessity. I can do this in seconds with DB2, but can't quite translate for Oracle.
My attempt:
variable refcur refcursor;
declare
my_select varchar2(64);
cursor c_tables is
select table_name
from all_tables
where owner='ABC' and table_name like 'ABC%';
begin
for x in c_tables
loop
dbms_output.put_line(x.table_name);
my_select := 'select * from ' || x.table_name;
open :refcur for my_select;
end loop;
exception
when no_data_found
then dbms_output.put_line('Nothing is found');
end;
/
In all of my attempts, the best I have gotten is table does not exist
Thanks
I don't know how you're logged on, but if you're NOT logged on as ABC you'll need to include the schema along with the table name, e.g.
my_select := 'select * from ' || x.owner || '.' || x.table_name;
Also, opening a cursor doesn't fetch anything from it, or display the data anywhere. You'll need to add logic to fetch data from the cursor, display the data, and close the cursor. And because the table name isn't fixed the database can't tell ahead a time what your row looks like so you'll need to get familiar with the DBMS_SQL package, which is used for handling dynamic SQL like this.
Best of luck.
you can user below example:
create or replace procedure app_test(v_tab varchar2) is
type cur_type is ref cursor;
my_cur cur_type;
v_name varchar2(20);
dyna_sql varchar2(4000);
begin
dyna_sql := 'select username from ' || v_tab || ' where rownum=1';
open my_cur for dyna_sql;
fetch my_cur
into v_name;
while my_cur%found LOOP
fetch my_cur
into v_name;
DBMS_output.put_line(v_name);
end loop;
close my_cur;
end app_test;

How to determine row count for all tables in an Oracle Schema [duplicate]

I am trying to get the record counts of all tables in a schema. I am having trouble writing the PL/SQL. Here is what I have done so far, but I am getting errors. Please suggest any changes:
DECLARE
v_owner varchar2(40);
v_table_name varchar2(40);
cursor get_tables is
select distinct table_name,user
from user_tables
where lower(user) = 'SCHEMA_NAME';
begin
open get_tables;
fetch get_tables into v_table_name,v_owner;
INSERT INTO STATS_TABLE(TABLE_NAME,SCHEMA_NAME,RECORD_COUNT,CREATED)
SELECT v_table_name,v_owner,COUNT(*),TO_DATE(SYSDATE,'DD-MON-YY') FROM v_table_name;
CLOSE get_tables;
END;
This can be done with a single statement and some XML magic:
select table_name,
to_number(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) c from '||owner||'.'||table_name)),'/ROWSET/ROW/C')) as count
from all_tables
where owner = 'FOOBAR'
This should do it:
declare
v_count integer;
begin
for r in (select table_name, owner from all_tables
where owner = 'SCHEMA_NAME')
loop
execute immediate 'select count(*) from ' || r.table_name
into v_count;
INSERT INTO STATS_TABLE(TABLE_NAME,SCHEMA_NAME,RECORD_COUNT,CREATED)
VALUES (r.table_name,r.owner,v_count,SYSDATE);
end loop;
end;
I removed various bugs from your code.
Note: For the benefit of other readers, Oracle does not provide a table called STATS_TABLE, you would need to create it.
select owner, table_name, num_rows, sample_size, last_analyzed from all_tables;
This is the fastest way to retrieve the row counts but there are a few important caveats:
NUM_ROWS is only 100% accurate if statistics were gathered in 11g and above with ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE (the default), or in earlier versions with ESTIMATE_PERCENT => 100. See this post for an explanation of how
the AUTO_SAMPLE_SIZE algorithm works in 11g.
Results were generated as of LAST_ANALYZED, the current results may be different.
If you want simple SQL for Oracle (e.g. have XE with no XmlGen) go for a simple 2-step:
select ('(SELECT ''' || table_name || ''' as Tablename,COUNT(*) FROM "' || table_name || '") UNION') from USER_TABLES;
Copy the entire result and replace the last UNION with a semi-colon (';'). Then as the 2nd step execute the resulting SQL.
Get counts of all tables in a schema and order by desc
select 'with tmp(table_name, row_number) as (' from dual
union all
select 'select '''||table_name||''',count(*) from '||table_name||' union ' from USER_TABLES
union all
select 'select '''',0 from dual) select table_name,row_number from tmp order by row_number desc ;' from dual;
Copy the entire result and execute
You have to use execute immediate (dynamic sql).
DECLARE
v_owner varchar2(40);
v_table_name varchar2(40);
cursor get_tables is
select distinct table_name,user
from user_tables
where lower(user) = 'schema_name';
begin
open get_tables;
loop
fetch get_tables into v_table_name,v_owner;
EXIT WHEN get_tables%NOTFOUND;
execute immediate 'INSERT INTO STATS_TABLE(TABLE_NAME,SCHEMA_NAME,RECORD_COUNT,CREATED)
SELECT ''' || v_table_name || ''' , ''' || v_owner ||''',COUNT(*),TO_DATE(SYSDATE,''DD-MON-YY'') FROM ' || v_table_name;
end loop;
CLOSE get_tables;
END;

Resources