I have code_table which contain the below columns:
- ID
- FIELD_NAME
- TABLE_NAME
- WHERE_CONDITION
now, I need to write select statement that return table contain 2 columns, the first column is code_table.ID, and the other column is the result of the below select statement
select code_table.FIELD_NAME
from code_table.TABLE_NAME
where code_table.WHERE_CONDITION = 1;
how can I solve it ?
Try this using anonymous block. Hope this helps
DECLARE
cursor cur_code_tab is
select id,field_name,table_name,where_condition from code_table;
sql_query varchar2(500);
BEGIN
for i in cur_code_tab loop
sql_query:='select '''||i.id||''','||i.field_name||' from '||i.table_name||' where '||i.where_condition=1;
execute immediate(sql_query);
end loop;
END;
Related
declare
vquery long;
cursor c1 is
select * from temp_name;
begin
for i in c1
loop
vquery :='INSERT INTO ot.temp_new(id)
select '''||i.id||''' from ot.customers';
dbms_output.put_line(i.id);
end loop;
end;
/
Output of select * from temp_name is :
ID
--------------------------------------------------------------------------------
customer_id
1 row selected.
I have customers table which has customer_id column.I want to insert all the customer_id into temp_new table but it is not being inserted. The PLSQL block executes successfully but the temp_new table is empty.
The output of dbms_output.put_line(i.id); is
customer_id
What is wrong there?
The main problem is that you generate a dynamic statement that you never execute; at some point you need to do:
execute immediate vquery;
But there are other problems. If you output the generated vquery string you'll see it contains:
INSERT INTO ot.temp_new(id)
select 'customer_id' from ot.customers
which means that for every row in customers you'll get one row in temp_new with ID set to the same fixed literal 'customer_id'. It's unlikely that's what you want; if customer_id is a column name from customers then it shouldn't be in single quotes.
As #mathguy suggested, long is not a sensible data type to use; you could use a CLOB but only really need a varchar2 here. So something more like this, where I've also switched to use an implicit cursor:
declare
l_stmt varchar2(4000);
begin
for i in (select id from temp_name)
loop
l_stmt := 'INSERT INTO temp_new(id) select '||i.id||' from customers';
dbms_output.put_line(i.id);
dbms_output.put_line(l_stmt);
execute immediate l_stmt;
end loop;
end;
/
db<>fiddle
The loop doesn't really make sense though; if your temp_name table had multiple rows with different column names, you'd try to insert the corresponding values from those columns in the customers table into multiple rows in temp_new, all in the same id column, as shown in this db<>fiddle.
I guess this is the starting point for something more complicated, but still seems a little odd.
I have table:
BOOK_DT1 BOOK_DT2 USERNAME
--------- --------- --------------------
22-SEP-17 12-OCT-17 rSK
08-FEB-16 18-FEB-16 chak
05-JAN-17 12-JAN-17 rah
31-JAN-16 01-JUL-16 ABC
While inserting another column, it should check the given dates for BOOK_DT1 and BOOK_DT2 should not come into the dates present in the table.
For EX: insert into table_name('28-SEP-17','12-NOV-17','XYX'); should throw an error, because '28-SEP-17' comes in between 22-SEP-17 and 12-OCT-17.
you can achive this using the after insert trigger. Somting like this:
create or replace trigger date_check_trg
after insert
on your_table_name
v_cnt NUMBER;
begin
select count(*)
into v_cnt
from you_table_name t1
join you_table_name t2
on ( t1.BOOK_DT1 between t2.BOOK_DT1 and t2.BOOK_DT1
or t1.BOOK_DT2 between t2.BOOK_DT1 and t2.BOOK_DT1
)
AND t1.rowid != t2.rowid
;
if v_cnt > 0 then
raise_application_error(-20999, 'intersection error');
end if;
end;
/
If you want to check before the insert then BEFORE INSERT should be what you're looking for. If the name doesn't matter and your new values should not be between any values previously inserted in the table then this is how I would write it:
create or replace trigger trg_date_chk
before insert
on your_table_name for each row
declare
lnCnt NUMBER;
begin
select count(*)
into lnCnt
from you_table_name a
where :new.BOOK_DT1 < a.BOOK_DT1
and :new.BOOK_DT2 > a.BOOK_DT2;
if lnCnt > 0 then
raise_application_error(-20999, 'INSERT ERROR HERE');
end if;
end;
/
I'm trying to use the rownum to simulate a column autonumbered as I need to use it as an ID. Since it is an ID, I look at the final table if no record with MAX (ID).
The problem I have is when I want to do arithmetic operations within the cursor or when you invoke, or when you want to use a function. The ROWNUM (v_id) field is empty me when I want to print with DBMS_OUTPUT . Anyone have any idea how to solve it without using sequences ?
Here put the sample code.
declare
max_id number;
CURSOR INSRT(w_max number) IS
SELECT f_max_fact_sap(to_number(V_ID),w_max) AS V_ID,Seriei,serief
FROM (SELECT To_Char(ROWNUM) AS V_ID, A.*
FROM (SELECT DISTINCT a.matnr, a.seriei, a.serief,a.xblnr,a.fecha_sap, ((SERIEF-SERIEI)+1) AS rango
FROM SOPFUN.TT_ZMOVIMI_FACTURADAS a
WHERE 0 =(SELECT COUNT(1)
FROM PA_ZMOVIMI_FACTURADAS B
WHERE A.SERIEI = B.SERIEI
AND A.SERIEF = B.SERIEF
AND A.MATNR = B.MATNR
AND A.FECHA_SAP=B.FECHA_SAP)
AND A.FECHA_SAP IS NOT NULL) A);
TYPE T_INSRT IS TABLE OF INSRT%ROWTYPE INDEX BY PLS_INTEGER;
V_INSRT T_INSRT;
begin
SELECT Max(Nvl(ID,10000)) INTO MAX_ID-- To Proof because the table is empty
FROM PA_ZMOVIMI_FACTURADAS;
OPEN INSRT(MAX_ID);
LOOP
FETCH INSRT BULK COLLECT INTO V_INSRT LIMIT 1000;
FOR I IN 1 .. V_INSRT.Count loop
DBMS_OUTPUT.PUT_LINE('ID: ' ||V_INSRT(I).V_ID||' SI: '||V_INSRT(I).SERIEI||' SI: '||V_INSRT(I).SERIEF||' OPERACION: '||to_char(f_max_fact_sap(V_INSRT(I).V_ID,MAX_ID)));
end loop;
EXIT WHEN INSRT%NOTFOUND;
END LOOP;
end;
I have to generate a table (contains two columns) of random data from a database table through oracle procedure. The user can indicate the number of data required and we have to use the table data with ID values from 1001 to 1060. I am trying to use cursor loop and not sure dbms_random method dhould I use.
I am using the following code to create procedure
create or replace procedure a05_random_plant(p_count in number)
as
v_count number := p_count;
cursor c is
select plant_id, common_name
from ppl_plants
where rownum = v_count
order by dbms_random.value;
begin
delete from a05_random_plants_table;
for c_table in c
loop
insert into a05_random_plants_table(plant_id, plant_name)
values (c_table.plant_id, c_table.common_name);
end loop;
end;
/
it complied successfully. Then I executed with the following code
set serveroutput on
exec a05_random_plant(5);
it shows anonymous block completed
but when run the following code, I do not get any records
select * from a05_random_plants_table;
The rownum=value would not work for a value greater than 1
hence try the below
create or replace procedure a05_random_plant(p_count in number)
as
v_count number := p_count;
cursor c is
select plant_id, common_name
from ppl_plants
where rownum <= v_count
order by dbms_random.value;
begin
delete from a05_random_plants_table;
for c_table in c
loop
insert into a05_random_plants_table(plant_id, plant_name)
values (c_table.plant_id, c_table.common_name);
end loop;
end;
/
Query by Tom Kyte - will generate almost 75K of rows:
select trunc(sysdate,'year')+mod(rownum,365) TRANS_DATE,
mod(rownum,100) CUST_ID,
abs(dbms_random.random)/100 SALES_AMOUNT
from all_objects
/
You can use this example to write your query and add where clause to it - where id between 1001 and 1060, for example.
I don't think you should use a cursor (which is slow naturally) but do a direct insert from a select:
insert into table (col1, col2)
select colx, coly from other_table...
And, isn't missing a COMMIT on the end of your procedure?
So, all code in your procedure would be a DELETE, a INSERT WITH that SELECT and then a COMMIT.
Here is my code:
create or replace
procedure postGateway (flgManual in nvarchar2, segmentID in number) as
sequel string(2000);
cursor download_cursor is
select downloadid from ipcsdd_download_process where status LIKE 'W' OR status
LIKE 'E';
cursor table_cursor is
select table_name from user_tab_columns where column_name = 'DOWNLOADID' and
table_name like 'IPCSDD%' OR table_name like 'IPCSCUSTDD' group by table_name;
begin
for download in download_cursor
loop
dbms_output.put_line('DownloadID: ' || download.downloadid );
for usertable in table_cursor
loop
sequel:=' select * FROM'||usertable.table_name||'where downloadid='||download.downloadid;
execute immediate sequel;
dbms_output.put_line(' select * from'||usertable.table_name||'where downloadid='||download.downloadid);
end loop;
end loop;
end postGateway ;
What I doing here is: In first cursor I am trying to get the downloadids whose status are W or E. In the second cursor I am trying to get the tables which have downloadid coloumn and those table name should start with IPCSDD or IPCSCUSTDD.
Now I have to write a query such that In every table starting from IPCSDD that i get from cursor 2 i need to see if a data is present for the downloadid that i get from cursor 1. I tried writing dynamic sql but it gives me error saying "00923. 00000 - "FROM keyword not found where expected"" .
How can I achieve this?
Thanks
You simply neglected to add spaces after and before your keywords, with a space after FROM and a space before where:
sequel:=' select * FROM '||usertable.table_name||' where downloadid='||download.downloadid;