Code to execute select on list of multiple Oracle databases - sql

Need your or guidance on how I can execute a select on multiple databases provided in the list. the goal behind this code is to query multiple remote databases and insert the output in current database.
Need to db_link to be fetched from a list or table
insert into xxxx.DB_tracker value(SELECT d.name FROM v$database#**opXXX_du**);

Dynamic SQL.
Suppose that database links are stored in the link table:
SQL> select * From links;
LINK
---------
dbl_ora10
dbl_ora11
dbl_orcl
You'd then use a loop, create an insert statement and execute it. As I don't have those database links, I'm just displaying statements to the screen. You'd uncomment the execute immediate line.
SQL> set serveroutput on
SQL> declare
2 l_str varchar2(200);
3 begin
4 for cur_r in (select link from links) loop
5 l_str := 'insert into db_tracker ' ||
6 'select name from v$database#' || cur_r.link;
7 dbms_output.put_line(l_str);
8
9 -- execute immediate l_str;
10 end loop;
11 end;
12 /
insert into db_tracker select name from v$database#dbl_ora10
insert into db_tracker select name from v$database#dbl_ora11
insert into db_tracker select name from v$database#dbl_orcl
PL/SQL procedure successfully completed.
SQL>
If you want to actually select name and display it on the screen, then you need the into clause. Something like this:
SQL> set serveroutput on
SQL>
SQL> declare
2 l_name varchar2(30);
3 begin
4 for cur_r in (select link from links) loop
5 execute immediate 'select name from v$database#' || cur_r.link
6 into l_name;
7 dbms_output.put_line(l_name);
8 end loop;
9 end;
10 /
XE
PL/SQL procedure successfully completed.
SQL>

Related

How do I run a count of rows over a database link?

This code, works. It runs a row count the way you'd expect, I want to tweek it, mostly to do a count over a db_link for tables dictated as I see fit.
declare
n number;
begin
for i in (select table_name from user_tables) loop
execute immediate' select count(*) from '||i.table_name into n;
dbms_output.put_line('Table Name: '||i.table_name||' Count of Row''s: '||n);
end loop;
end;
/
So, this is the adapted code... it includes a variable with the name of the link. (The link works fine) But how to reference it is probably where I'm coming unstuck.
declare
l_dblink varchar2(100) := 'DB1';
n number;
begin
for i in (select table_name from my_tables) loop
execute immediate' select count(*) from '||i.table_name#||l_dblink into n;
dbms_output.put_line('Table Name: '||i.table_name||' Count of Row''s: '||n);
end loop;
end;
/
Can someone please have a look and tell me where I'm going wrong? I just want the SQL to pick up the table names from a local table, and then use the names to count the rows in those tables, which reside in the remote database.
Monkey is on the wrong tree and can't eat a banana.
SQL> create table my_tables (table_name varchar2(20));
Table created.
SQL> insert into my_tables values ('dual');
1 row created.
SQL> set serveroutput on
SQL> declare
2 l_dblink varchar2(100) := 'db1';
3 n number;
4 begin
5 for i in (select table_name from my_tables) -- has to be like this
6 loop -- vvv
7 execute immediate' select count(*) from '||i.table_name || '#' || l_dblink into n;
8 dbms_output.put_line('Table Name: '||i.table_name||' Count of Row''s: '||n);
9 end loop;
10 end;
11 /
Table Name: dual Count of Row's: 1
PL/SQL procedure successfully completed.

PL/SQL procedure to accept an item_num and report its description,price,and on_hand quantity is not working

This is a homework assignment in my database management class. We were given the option of using Oracle SQL Developer on campus computers, or using SSH Secure Shell (I am using the later). I am to write a procedure which accepts an item_num and reports its description, price, and on_hand quantity. (Btw: all of these come from a table named "item".) My professor has said that a few commands (listed above the procedure) must proceed the procedure. My code:
serveroutput on;
accept item_num prompt 'Enter a item_num: ';
exec reports_item_info();
create or replace procedure reports_item_info (i_item_num in
item.item_num%type) as
i_description item.descripton%type;
i_std_price item.std_price%type;
i_on_hand item.on_hand%type;
begin
select description,std_price,on_hand
into i_description,i_std_price,i_on_hand
from item
where item_num = i_item_num;
dbms_output.put_line(rtrim(i_description))||' '||
(rtrim(i_std_price))||' '||(rtrim(i_on_hand))
end;
/
I know that something isn't right, because it doesn't work. How could I alter it, so that it will work?
If you pay attention to what you type, it works; you didn't provide CREATE TABLE so I created it myself.
SQL> create table item (item_num number,
2 description varchar2(20),
3 std_price number,
4 on_hand number);
Table created.
SQL>
SQL> create or replace procedure reports_item_info
2 (i_item_num in item.item_num%type)
3 as
4 i_description item.description%type;
5 i_std_price item.std_price%type;
6 i_on_hand item.on_hand%type;
7 begin
8 select description, std_price, on_hand
9 into i_description, i_std_price, i_on_hand
10 from item
11 where item_num = i_item_num;
12
13 dbms_output.put_line(rtrim(i_description) ||' '||
14 rtrim(i_std_price) ||' '||
15 rtrim(i_on_hand)
16 );
17 end;
18 /
Procedure created.
SQL>
Testing:
SQL> insert into item values (1, 'test', 100, 10);
1 row created.
SQL> exec reports_item_info(1);
test 100 10
PL/SQL procedure successfully completed.
SQL>
Your mistakes?
it is not a DESCRIPTON but DESCRIPTION
missing semi-colon at the end of DBMS_OUTPUT.PUT_LINE call
superfluous parenthesis
[EDIT]
Try with this:
SQL> declare
2 item_num number := &enter_item_num_value;
3 begin
4 reports_item_info(item_num);
5 end;
6 /
Enter value for enter_item_num_value: 1
old 2: item_num number := &enter_item_num_value;
new 2: item_num number := 1;
test 100 10
PL/SQL procedure successfully completed.
SQL>
or
SQL> accept itnum prompt 'Enter value : ';
Enter value : 1
SQL> exec reports_item_info(&itnum);
test 100 10
PL/SQL procedure successfully completed.
SQL>
The problem is due to the usage of dbms_output.put_line make it as
dbms_output.put_line(rtrim(i_description)||' '||rtrim(i_std_price)||' '||rtrim(i_on_hand));
by removing redundant parentheses.
Put a semi-colon at the end of this statement of course.
And there's a problem in spelling of the column description.
Then, use the following :
SQL> set serveroutput on;
SQL> CREATE TABLE item(
item_num varchar2(50),
description varchar2(100),
std_price number(10,2),
on_hand varchar2(100)
);
SQL> INSERT INTO item VALUES ('AH74, BR23, CD33','abc',15.75,'defgh');
SQL> COMMIT;
SQL> create or replace procedure reports_item_info(i_item_num in item.item_num%type) as
i_description item.description%type;
i_std_price item.std_price%type;
i_on_hand item.on_hand%type;
begin
select description, std_price, on_hand
into i_description, i_std_price, i_on_hand
from item
where item_num = i_item_num;
dbms_output.put_line(rtrim(i_description) || ' '|| rtrim(i_std_price)||' '||rtrim(i_on_hand));
end;
/
SQL> accept item_num prompt 'Enter a item_num: '; -- enter AH74, BR23, CD33 when prompts
SQL> exec reports_item_info('&item_num'); -- use parameter with quotes
abc 15.75 defgh
PL/SQL procedure successfully completed

create table via execute immediate does not work

I'm experiencing a problem with the PLSQL block below. When the code is executed as written below (without the loop) the script is successful. However when the loop is uncommented I get an error that the table in the select statement was not found. When I check, I find that indeed the table was not created at all. It's almost as if the loop tries to runs before the execute immediate.
Yes I am aware that since the table is not populated anyway the print statement would not appear regardless however I would not expect the query to fail.
begin
execute immediate 'create table tbl_temp (oid_value number(20) ,rowid_field varchar2(20))';
/*for nullval in (select oid_value from tbl_temp)
loop
DBMS_OUTPUT.PUT_LINE('something');
end loop;*/
end;
When you try to run this code, Oracle first checks if it is correct, thus checking if all the tables it uses exist.
At the beginning, your table does not exist, so this code will give an error and nothing will be done.
If you want to create a table on the fly and then make a query on it ( and I believe this is not a great idea), you could use a cursor based on a dynamic SQL; for example:
SQL> select * from tbl_temp;
select * from tbl_temp
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> declare
2 cur sys_refcursor;
3 val number(20);
4 begin
5 execute immediate 'create table tbl_temp (oid_value number(20) ,rowid_field varchar2(20))';
6
7 open cur for 'select oid_value from tbl_temp';
8 loop
9 fetch cur into val;
10 exit when cur%notfound;
11 dbms_output.put_line('val = ' || val);
12 end loop;
13 end;
14
15
16 /
PL/SQL procedure successfully completed.
SQL> select * from tbl_temp;
no rows selected
SQL>

How to select from query string in oracle

Lets assume, I have a string that holds a query string.
How can I select the rows from that query string in oracle ?
I tried execute immediate but it returns nothing.
declare
hello varchar(30000);
begin
hello:='select * from test_table';
execute immediate hello;
end;
You would use a dynamic cursor.
Here's an example with SQL*Plus:
SQL> var dyn_cur refcursor
SQL> DECLARE
2 l_sql_query VARCHAR2(1000);
3 BEGIN
4 -- complex function that returns a query:
5 l_sql_query := 'SELECT 1, dummy FROM dual';
6 OPEN :dyn_cur FOR l_sql_query;
7 END;
8 /
PL/SQL procedure successfully completed.
SQL> print dyn_cur
1 DUM
---------- ---
1 X
You can use dynamic cursors in PL/SQL procedures and packages:
SQL> CREATE OR REPLACE PROCEDURE prc_dyn_cur(p_dyn_cursor OUT SYS_REFCURSOR) IS
2 BEGIN
3 OPEN p_dyn_cursor FOR 'SELECT 1, dummy FROM dual';
4 END;
5 /
Procedure created.
SQL> exec prc_dyn_cur(:dyn_cur);
PL/SQL procedure successfully completed.
SQL> print dyn_cur
1 DUM
---------- ---
1 X
declare
hello varchar(30000);
type tb is table of test_table$rowtype;
mytb tb;
begin
hello:='select * from test_table';
execute immediate hello bulk collect into mytb;
-- now you got all og youe data in the "array" mytb
end;
notice that this solution takes into account that you know what table you are selecting from.
plus, i think you should describe what exactly it is you are trying to achieve.
CREATE OR REPLACE PROCEDURE query_executer (string_query IN VARCHAR)
IS
c1 SYS_REFCURSOR;
v_last_name employees.last_name%TYPE; -- Selecting last_name
BEGIN
OPEN c1 FOR string_query; -- Opening c1 for the select statement
LOOP
FETCH c1 INTO v_last_name;
DBMS_OUTPUT.put_line (v_last_name);
EXIT WHEN (C1%NOTFOUND);
END LOOP;
END;
SET SERVEROUTPUT ON
EXECUTE query_executer('select last_name from employees');
OUTPUT
Procedure created.
Abel
Ande
Atkinso
PL/SQL procedure successfully completed.

oracle - mixing SQL code with PLSQL when no bindings in WHERE statement

I am trying to write a very simple sql script:
select * from table_X;
and I would like to see the results in oracle sqlplus, if there are any. These results are important for further analysis.
Also to mention, it depends, how many tables were created originally, so chances are that table_X may not be in the database at all. However I want to avoid getting an error, when parsing, that table_X doesn't exist, while running that script above.
So I was trying to wrap that SQL into some PLSQL dynamic code, like this:
Define table_X="MY_TAB"
DECLARE
stmt_ VARCHAR2(2000);
exist_ number := 0;
CURSOR table_exist IS
SELECT 1
FROM user_tables
WHERE table_name = '&table_X';
BEGIN
OPEN table_exist;
FETCH table_exist INTO exist_;
CLOSE table_exist;
IF exist_ = 1 THEN
stmt_ := 'SELECT * FROM &table_X';
EXECUTE IMMEDIATE stmt_;
ELSE
dbms_output.put_line('This functionality is not installed.');
END IF;
END;
/
Why I cannot see any result (records), if there is data in MY_TAB? Do I really need to bind some columns and use ex. dbms_output to be able to see some information?
Is there any simple way to query a table without getting 'ORA-00942: table or view does not exist'
if that table doesn't exist (ideally using SQL only)?
Thanks in advance
like this if you want it in sqlplus:
SQL> var c refcursor;
SQL> create or replace function get_table(p_tab in varchar2)
2 return sys_refcursor
3 is
4 v_r sys_refcursor;
5 NO_TABLE exception;
6 pragma exception_init(NO_TABLE, -942);
7 begin
8 open v_r for 'select * from ' || dbms_assert.simple_sql_name(p_tab);
9 return v_r;
10 exception
11 when NO_TABLE
12 then
13 open v_r for select 'NO TABLE ' || p_tab as oops from dual;
14 return v_r;
15 end;
16 /
Function created.
SQL> exec :c := get_table('DUAL2');
PL/SQL procedure successfully completed.
SQL> print c
OOPS
-----------------------------------------
NO TABLE DUAL2
SQL>
SQL> exec :c := get_table('DUAL');
PL/SQL procedure successfully completed.
SQL> print c
D
-
X
Instead of execute immediate 'query' you could use execute immediate 'query' bulk collect into and then loop over it and use dbms_output to print it.
http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/executeimmediate_statement.htm