How do I insert data from a table to the XML table - sql

When I run this code I didn't get the right data from the standard table
create table COUNTRY_XML(
C_X sys.xmltype);
begin
for cursor in
(select country, continental, population2019 from countries)
loop
insert into country_xml values(
sys.xmltype.createXML(
'<ac_x createdby="Guangzhe">
<country_info>
<Country>mycursor.country</Country>
<Continental>mycursor.continental</Continental>
<Population2019>mycursor.population2019</Population2019>
</country_info>
</ac_x>'));
end loop;
end;
select c.c_x.extract('/').getstringval() from country_xml c
There results are as follow and they are all the same things for each row.
"<ac_x createdby="Guangzhe">
<country_info>
<Country>mycursor.country</Country>
<Continental>mycursor.continental</Continental>
<Population2019>mycursor.population2019</Population2019>
</country_info>
</ac_x>"

You are not doing concatnation properly.
You need to use || (concatanation operator) as following
Table creation
SQL> CREATE TABLE COUNTRY_XML (
2 C_X SYS.XMLTYPE
3 );
Table created.
Solution you need:
SQL>
SQL> begin
2 for mycursor in -- changed the name
3 (select 'INDIA' as country, 'ASIA' as continental, '130B' as population2019 from dual)
4 --(select country, continental, population2019 from countries)
5 loop
6 insert into country_xml values(
7 sys.xmltype.createXML(
8 '<ac_x createdby="Guangzhe">
9 <country_info>
10 <Country>' || mycursor.country || '</Country>
11 <Continental>' || mycursor.continental|| '</Continental>
12 <Population2019>' || mycursor.population2019|| '</Population2019>
13 </country_info>
14 </ac_x>'));
15 end loop;
16 end;
17 /
PL/SQL procedure successfully completed.
Output
SQL> SELECT C.C_X.EXTRACT('/').GETSTRINGVAL()
2 FROM COUNTRY_XML C
3 ;
C.C_X.EXTRACT('/').GETSTRINGVAL()
--------------------------------------------------------------------------------
<ac_x createdby="Guangzhe">
<country_info>
<Country>INDIA</Country>
<Continental>ASIA</Continental>
<Population2019>130B</Population2019>
</country_info>
</ac_x>
SQL>
Cheers!!

Related

How to dynamically construct table name

I would like to construct a query where a table name is based off of another table's column mod 12. For example:
SELECT *
FROM table_b_XX
where XX here is determined by table_a.column_a % 12.
Presuming you have such a tables:
SQL> create table table_a as
2 select 1212 as column_a from dual;
Table created.
As the following result returns 0, we need table_b_00 so I'll create it:
SQL> select mod(1212, 12) from dual;
MOD(1212,12)
------------
0
SQL> create table table_b_00 as select 'table 00' name from dual;
Table created.
SQL> create table table_b_01 as select 'table 01' name from dual;
Table created.
Now, create a function which returns ref cursor; it selects rows from a table whose name is designed by the help of the table_a contents:
SQL> create or replace function f_test return sys_refcursor
2 is
3 l_str varchar2(200);
4 rc sys_refcursor;
5 begin
6 select 'select * from table_b_' || lpad(mod(a.column_a, 12), 2, '0')
7 into l_str
8 from table_a a;
9
10 open rc for l_str;
11 return rc;
12 end f_test;
13 /
Function created.
Let's try it:
SQL> select f_test from dual;
F_TEST
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
NAME
--------
table 00
Right; that's contents of table_b_00.
Consider the following meta code:
DECLARE
n VARCHAR2(32767);
r VARCHAR2(32767);
BEGIN
SELECT column_a INTO name FROM table_a;
EXECUTE IMMEDIATE 'SELECT r FROM table_b_'||n INTO r;
END;
/

ORACLE PL/SQL : Join cursor in subselect

Is is possible to use cursor as a part of statement. Lets say i have something like this (pseudo code)
CURSOR SOURCE IS
SELECT
ID,
FLAG
FROM TABLE_OLD_A
WHERE 1=1;
TYPE t_new_a IS TABLE OF TABLE_NEW_A%ROWTYPE INDEX BY BINARY_INTEGER;
var_t_new_a t_new_a;
OPEN SOURCE;
FETCH SOURCE BULK COLLECT INTO var_t_new_a;
CLOSE SOURCE;
so far it works.
Now I would like to check if the migration from old to new is ok
WITH OLD_SOURCE AS
(
SELECT
ID,
FLAG
FROM SOURCE -> can i use cursor here in order not to copy the same select from cursor ?
)
SELECT COUNT(*) FROM TABLE_NEW_A
WHERE EXISTS
(
SELECT *
FROM OLD_SOURCE
WHERE 1=1
AND TABLE_NEW_A.ID = OLD_SOURCE.ID
AND TABLE_NEW_A.FLAG = OLD_SOURCE.FLAG
);
You can use the XML and TABLE function approach as follows to use the cursor in the query as a table as follows:
SQL> SET SERVEROUT ON
SQL> DECLARE
2 CUR SYS_REFCURSOR; -- DECLARING THE CURSOR
3 L_COUNT NUMBER;
4 BEGIN
5 --OPENING THE CURSOR
6 OPEN CUR FOR
7 SELECT 1 AS A, 5 AS B FROM DUAL UNION ALL
8 SELECT 3 AS A, 12 AS B FROM DUAL;
9
10 -- USING THE CURSOR AS A TABLE
11 SELECT MAX(B - A)
12 INTO L_COUNT
13 -- FOLLOWING CODE CONVERTS THE CURSOR TO TABLE
14 FROM (
15 SELECT EXTRACTVALUE(VALUE(SRC),'ROW/A') A,
16 EXTRACTVALUE(VALUE(SRC),'ROW/B') B
17 FROM TABLE ( XMLSEQUENCE(
18 XMLTYPE(CUR).EXTRACT('ROWSET/ROW')
19 ) ) SRC
20 ) CUR_TABLE;
21
22 DBMS_OUTPUT.PUT_LINE('Result: ' || L_COUNT);
23 END;
24 /
Result: 9
PL/SQL procedure successfully completed.
SQL>

How to use 'sysdate' if its a string constant

I extract data from a table, the field is mostly null, but sometimes it's sysdate. However since its from a table, after getting the field its 'sysdate', between single quotes. How can I use it?
I have tried to_date, to_date(to_char()).
I need something that works within
select to_date('sysdate') from dual;
You can use a case expression:
select case
when the_column = 'sysdate' then sysdate
else to_date(the_column)
end as date_value
from the_table;
The only way I know is dynamic SQL. Here's an example:
SQL> create table test (id number, col varchar2(20));
Table created.
SQL> insert into test
2 select 1, '''sysdate''' from dual union all
3 select 2, null from dual;
2 rows created.
SQL> declare
2 l_res test%rowtype;
3 l_str varchar2(200);
4 begin
5 for cur_r in (select id, col from test) loop
6 l_str := 'select ' || cur_r.id ||', '||
7 nvl(replace(cur_r.col, chr(39), null), 'null') || ' from dual';
8 execute immediate l_str into l_res;
9 dbms_output.put_line(l_res.id ||': '|| l_res.col);
10 end loop;
11 end;
12 /
1: 24.06.2019 12:18:39
2:
PL/SQL procedure successfully completed.
SQL>

Is it possible to pass a table name to a SQL query by select query in oracle

Is it possible to pass a table name to a query using a result of another query?
SELECT T.MID, T.TID, M.NAME
FROM 'ONLINETRANSACTION#(' || SELECT ONLINEDBLINK FROM PARAMETERTABLE ||')' T
LEFT JOIN 'ONLINEMERCHANT#(' || SELECT ONLINEDBLINK FROM PARAMETERTABLE ||')' M
ON T.MID = M.MID
I have tried with the above code but it doesn't work.
This is a simple example based on Scott's schema.
lines 5 - 7 select your "table name" (actually, it appears that it is a database link name in your code. Doesn't matter, the principle is just the same)
line 9 uses that "table name" and concatenates it with the rest of the SELECT statement; finally, it executes it using EXECUTE IMMEDIATE
SQL> create table param (table_name varchar2(30));
Table created.
SQL> insert into param values ('EMP');
1 row created.
SQL> set serveroutput on
SQL> declare
2 l_table_name param.table_name%type;
3 l_max_sal emp.sal%type;
4 begin
5 select table_name into l_table_name
6 from param
7 where rownum = 1;
8
9 execute immediate 'select max(sal) from ' || l_table_name into l_max_sal;
10 dbms_output.put_line('Max salary = ' || l_max_sal);
11 end;
12 /
Max salary = 10000
PL/SQL procedure successfully completed.
SQL>

Oracle SQl Populating a cursor in a procedure from a sql statement saved in a table field

We want to populate a cursor in a procedure that is populated from a select statement in a table.
We created a table named stored_sql_statments with 2 columns, Created_date & Sql_statement.
In that table we will insert a select statement that selects other data from the database based on the clients needs.
Example:
insert into stored_sql_statments
( Created_date , Sql_statement)
values('2/1/2011', 'Select Client_idn , something_neat from cool_table where animal = 'dog' ')
Then in the procedure we have a bunch of code that does what it needs to do, which will never change, but the select statement we have in the cursor changes periodically. We always need to return 2 fields but the rest of the select statement changes.
So now we need to populate the cursor in the procedure with what the select statement coming form the table.
If it was returning only 1 row we have:
declare
x varchar2(600);
rec1 number(10);
rec2 varchar2(15);
begin
execute immediate select Sql_statement into x from stored_sql_statments where created_date = '2/1/2011';
execute immediate x into rec1, rec2;
...
This works, but we don't need it to go into 2 variables we need it to go into a cursor. The real select statement (the above code is just a simple example of what we need to do) is bringing back thousands of records so we need to use a cursor.
Hope this all makes sense
So if anyone knows how to do this, it would be appreciated.
Are you trying to dynamically populate a ref cursor? if so that isn't difficult to do:
set serveroutput on
declare
sql1 varchar2(500);
sql2 varchar2(500);
procedure runProcess(sqlstatement IN varchar2)
AS
refcrs sys_refcursor;
DTE DATE;
LEVELB NUMBER;
BEGIN
dbms_output.put_line(sqlstatement);
open refcrs for
sqlstatement; -- use 'using' to bind those variables
loop
fetch refcrs into DTE, LEVELB;
exit when refcrs%notfound;
dbms_output.put_line(TO_CHAR(DTE,'MMDDYYYY') || '/' || LEVELB);
end loop;
CLOSE REFCRS;
END runProcess;
begin
sql1 := 'select (sysdate - level) a, level b from dual connect by level < 5';
sql2:= 'select (sysdate + level) a, -level b from dual connect by level < 5';
runProcess(SQL1);
runProcess(SQL2);
end ;
/**
select (sysdate - level) a, level b from dual connect by level < 5
02102011/1
02092011/2
02082011/3
02072011/4
select (sysdate + level) a, -level b from dual connect by level < 5
02122011/-1
02132011/-2
02142011/-3
02152011/-4
**/
As you can see, I am dynamically executing two different select statements in the same procedure and outputting their results.
SQL> drop table stack_overflow;
Table dropped.
SQL> create table stack_overflow (created_date date constraint stack_overflow_pk primary key
2 , sql_statement varchar2(4000) not null)
3 /
Table created.
SQL> drop table source_data;
Table dropped.
SQL> create table source_data (vc varchar2(10) null
2 , n number);
Table created.
SQL> insert into source_data values ('a', 100);
1 row created.
SQL> insert into source_data values ('a', 0);
1 row created.
SQL> insert into source_data values ('b', 50);
1 row created.
SQL> insert into source_data values ('c', null);
1 row created.
SQL> insert into stack_overflow values (sysdate - 3/24, 'select vc, sum(n)
2 from source_data
3 group by vc
4 order by vc asc');
1 row created.
SQL> insert into stack_overflow values (sysdate - 2/24 , 'select vc, avg(n)
2 from source_data
3 group by vc
4 order by vc desc');
1 row created.
SQL> insert into stack_overflow values (sysdate - 1/24 , 'select vc, count(*)
2 from source_data
3 group by vc');
1 row created.
SQL> insert into stack_overflow values (sysdate, 'select vc, count(n)
2 from source_data
3 group by vc');
1 row created.
SQL> commit;
Commit complete.
SQL> declare
2 type stack_overflow_type is record (col_1 varchar2(10), col_2 number);
3 type stack_overflow_cur_type is ref cursor return stack_overflow_type;
4 cursor sql_statement_cur is select sql_statement
5 from stack_overflow
6 order by created_date;
7 --
8 function get_cursor_by_date (i_created_date in date) return stack_overflow_cur_type is
9 l_return_cur sys_refcursor; -- stack_overflow_cur_type;
10 l_sql_statement stack_overflow.sql_statement%TYPE;
11 begin
12 select sql_statement into l_sql_statement
13 from stack_overflow
14 where created_date = i_created_date;
15 --
16 open l_return_cur for l_sql_statement;
17 return l_return_cur;
18 end get_cursor_by_date;
19 --
20 procedure process_and_close_cursor (i_cursor in stack_overflow_cur_type) is
21 l_current_rec stack_overflow_type;
22 begin
23 loop
24 fetch i_cursor into l_current_rec;
25 exit when i_cursor%NOTFOUND;
26 dbms_output.put_line('col_1: ' || l_current_rec.col_1
27 || ' col_2: ' || to_number(l_current_rec.col_2));
28 end loop;
29 --
30 close i_cursor;
31 end;
32 --
33 begin
34 for l_row in (select created_date
35 from stack_overflow
36 order by created_date)
37 loop
38 dbms_output.put_line('Processing the SQL statement created on: '
39 || to_char(l_row.created_date, 'YYYY-MM-DD HH24:Mi:SS'));
40 --
41 process_and_close_cursor(get_cursor_by_date(l_row.created_date));
42 --
43 dbms_output.new_line;
44 end loop;
45 end;
46 /
Processing the SQL statement created on: 2011-02-11 10:01:16
col_1: a col_2: 100
col_1: b col_2: 50
col_1: c col_2:
Processing the SQL statement created on: 2011-02-11 11:01:16
col_1: c col_2:
col_1: b col_2: 50
col_1: a col_2: 50
Processing the SQL statement created on: 2011-02-11 12:01:17
col_1: a col_2: 2
col_1: b col_2: 1
col_1: c col_2: 1
Processing the SQL statement created on: 2011-02-11 13:01:17
col_1: a col_2: 2
col_1: b col_2: 1
col_1: c col_2: 0
PL/SQL procedure successfully completed.