Method to pass arguments to a procedure in oracle database - java

code in jsp page
cs=conn.prepareCall("{call held('"+session.getAttribute("roll")+"')}");
cs.executeUpdate();
in oracle database procedure is as
create or replace procedure "Held"
(s in Varchar2)
l_col_name varchar2(30);
begin
SELECT SUBJECTCODE
into l_col_name
FROM table02
WHERE SERIALNUMBER = '1';
execute immediate
'UPDATE TABLE01 SET '|| l_col_name || ' = '
|| l_col_name || ' + 1 WHERE Rollno = s'
;
end;
the following is the error
java.sql.SQLException: ORA-00904: "S": invalid identifier ORA-06512: at "ROHIT.HELD", line 12 ORA-06512: at line 1
please rectify it
i am trying to take the value of session ie from code in jsp and trying to use it in oracle database ....
i have used s as variable to store that value and used it in where clause
suggest a solution

I don't know if the jsp side is correct, but you clearly have a bug in your procedure.
When ORA-00904 occurs, you must enter a valid column name as it is
either missing or the one entered is invalid.
Here, your statement WHERE Rollno = s is understand as 'where column rollno is equal to column s', but the column s doesn't exist. I suppose you just have to move s out of the string.
execute immediate
'UPDATE TABLE01 SET '|| l_col_name || ' = '
|| l_col_name || ' + 1 WHERE Rollno = ''' || s || ''''
;

Related

Cannot perform fetch on a PLSQL statement

this is my table
CREATE TABLE accounts (
accountid VARCHAR(255),
name VARCHAR2(255),
phone_number INTEGER,
email_addresses VARCHAR2(255),
account_number VARCHAR(255),
password VARCHAR2(255)
);
and now i created one procedure
create or replace PROCEDURE getaccount (
param1 IN VARCHAR2
) AS
BEGIN
DBMS_OUTPUT.PUT_LINE(' SELECT
accountid,
password
FROM
accounts
WHERE
account_number = '||param1) ;
END getaccount;
and also why we used || or operator
second i run this code in SQLDEVELOPER
I GET THIS OUT
call getaccount('123456');
Call completed.
GET THIS MESSAGE
NOW I AM CONNECTING TO JAVA
HERE IS MY CODE IN JAVA
CallableStatement pst = Get.connection().prepareCall("{call getAccount(?)}");
pst.setString(1, Number);
ResultSet rs = pst.executeQuery();
if (rs.next()) {
System.out.println(rs.getString(1));
here Get.connection return Connection .
after i run this i get this error
Enter Account Number : 123456
java.sql.SQLException: Cannot perform fetch on a PLSQL statement: next
at ojdbc10/oracle.jdbc.driver.InsensitiveScrollableResultSet.next(InsensitiveScrollableResultSet.java:409)
at bank.services.SignValidator.getBank(SignValidator.java:20)
at bank.services.KingobankMain.getBank(KingobankMain.java:49)
at bank.services.KingobankMain.main(KingobankMain.java:14)
Your procedure does not return values (output variable ) and you are trying to get data.
This results in an error.
Stored Procedure OUT Parameters:
reate or replace procedure getaccount (
p_account_number in varchar2,
p_account_id out varchar2,
p_password out varchar2
) as
begin
select
accountid,
password
into
p_account_id,
p_password
from
accounts
where
account_number = p_account_number ;
end getaccount;
/
CallableStatement pst = Get.connection().prepareCall("{call getAccount(?,?,?)}");
pst.setString(1, "....");//set account number
pst.registerOutParameter(2, OracleTypes.VARCHAR);
pst.registerOutParameter(3, OracleTypes.VARCHAR);
pst.execute();
//read the OUT parameter now
System.out.println("AccountID="+pst.getString(2)+",password="+pst.getString(3));
..........your of code....
Stored Procedure Oracle SYS_REFCURSOR:
create or replace procedure getaccount (
p_account_number in varchar2,
p_cur out sys_refcursor
) as
begin
open p_cur for
select
accountid,
password
from
accounts
where
account_number = p_account_number ;
end getaccount;
/
CallableStatement pst = Get.connection().prepareCall("{call getAccount(?,?)}");
pst.setString(1, ".....");// set account number
pst.registerOutParameter(2, OracleTypes.CURSOR);
pst.execute();
//read the OUT parameter now
rs = (ResultSet) pst.getObject(2);
while(rs.next()){
System.out.println("AccountID="+rs.getString("accountid")+",password="+rs.getString("password"));
..........your of code....
}
Addition links:
JDBC Basics
Calling PL/SQL from Java
I don't know Java, but: procedure you wrote results in output displayed on the screen, but only if tool you used to call the procedure supports it - e.g. SQL*Plus, SQL Developer, TOAD and similar. For the rest, there will be no result at all.
It looks as if you wanted to run
select accountid, password from accoutns where account_number = 123456
in Java. You should then use a function instead of a procedure. It should return a VARCHAR2 (that select statement) and then you'd execute it in Java. How? Can't tell; as I said, I don't know Java. In Oracle, you'd use dynamic SQL.
Or, if it has to be a procedure, then it should have an OUT parameter so that it returns that select statement to the caller. But, caller then has to have "something" (a variable?) to accept that output into.
As you requested, a procedure with an OUT parameter:
CREATE OR REPLACE PROCEDURE getaccount (param1 IN VARCHAR2,
par_query OUT VARCHAR2)
AS
BEGIN
par_query :=
'SELECT accountid, password FROM accounts WHERE '
|| ' account_number = '
|| DBMS_ASSERT.enquote_literal (param1);
END getaccount;
Note dbms_assert, which is used to prevent SQL injection.
In order to run it in Oracle, you'd have to use a PL/SQL block with a variable that accepts the result returned by that procedure.
SQL> set serveroutput on
SQL>
SQL> create or replace procedure getaccount (param1 in varchar2,
2 par_query out varchar2)
3 as
4 begin
5 par_query :=
6 'SELECT accountid, password FROM accounts WHERE '
7 || ' account_number = '
8 || dbms_assert.enquote_literal (param1);
9 end getaccount;
10 /
Procedure created.
SQL> declare
2 l_out varchar2(200);
3 begin
4 getaccount('12345', l_out);
5 dbms_output.put_line('Result is: ' || l_out);
6 end;
7 /
Result is: SELECT accountid, password FROM accounts WHERE account_number = '12345'
PL/SQL procedure successfully completed.
SQL>
Apparently, you don't want to return a command represented as a string, but result that is produced by that select statement. As commented, consider returning a refcursor. Moreover, use a function instead of a procedure; they are designed to "return" a value. If it is a procedure, you'll have to create OUT parameter(s) and accept their values into something (local variables, probably).
Suppose this is table's contents:
SQL> select * From accounts;
ACCOUNTID PASSWORD ACCOUNT_NUMBER
---------- ---------- --------------------
1 my_pwd 12345
SQL>
Function that returns refcursor:
SQL> create or replace function getaccount (param1 in varchar2)
2 return sys_refcursor
3 is
4 l_rc sys_refcursor;
5 begin
6 open l_rc for
7 'SELECT accountid, password FROM accounts WHERE '
8 || ' account_number = '
9 || dbms_assert.enquote_literal (param1);
10 return l_rc;
11 end getaccount;
12 /
Function created.
SQL> select getaccount('12345') from dual;
GETACCOUNT('12345')
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
ACCOUNTID PASSWO
---------- ------
1 my_pwd
SQL>
Or, a procedure with 2 OUT parameters:
SQL> create or replace procedure getaccount
2 (param1 in varchar2,
3 p_accid out varchar2,
4 p_pwd out varchar2) is
5 begin
6 select accountid, password
7 into p_accid, p_pwd
8 from accounts
9 where account_number = param1;
10 end;
11 /
Procedure created.
SQL> set serveroutput on
SQL> declare
2 l_id varchar2(20);
3 l_pwd varchar2(20);
4 begin
5 getaccount('12345', l_id, l_pwd);
6 dbms_output.put_line('ID = ' || l_id ||', PWD = ' || l_pwd);
7 end;
8 /
ID = 1, PWD = my_pwd
PL/SQL procedure successfully completed.
SQL>

creating a trigger on a dynamically added table inside a procedure

I'am creating dynamic tables from java. What I want is that I want to create a trigger on every new table added which will just use the sequence to populate the primary key(serial_no) which is common in every table.How to achieve this ???
EDIT:
I have tried this code but I'am getting a message "procedure created with compilation errors"
create or replace procedure "TRIGGER_CALL" (trigger_name IN VARCHAR2, table_name IN VARCHAR2, sno IN NUMBER) as begin CREATE SEQUENCE abc MINVALUE 1 MAXVALUE 10000 INCREMENT BY 1 START WITH 141 CACHE 20 NOORDER NOCYCLE; CREATE OR REPLACE TRIGGER trigger_name before insert on table_name for each row begin select s_no.nextval into :new.sno from dual; end; end;
EDIT2:
My code
CREATE OR REPLACE
PROCEDURE "TRIGGER_CALL" (p_table_name IN VARCHAR2)
AUTHID CURRENT_USER
AS
l_sql VARCHAR2(4000);
l_dummy NUMBER;
l_trigger_name VARCHAR2(30);
l_seq_name VARCHAR2(30);
BEGIN
--SELECT '1'
--INTO l_dummy
--FROM all_tables
-- WHERE table_name = UPPER(p_table_name);
l_trigger_name := p_table_name || '_trg';
l_seq_name := p_table_name || 's_no';
EXECUTE IMMEDIATE 'CREATE SEQUENCE l_seq_name start with 1 increment by 1 ';
l_sql :=
'CREATE OR replace TRIGGER ' || l_trigger_name ||
' BEFORE INSERT ON ' || p_table_name ||
' FOR EACH ROW
BEGIN
SELECT l_seq_name.NEXTVAL
INTO :new.sno
FROM dual;
END;';
EXECUTE IMMEDIATE l_sql;
END;
/
Please check following code:
CREATE SEQUENCE my_sequence;
/
CREATE OR REPLACE
PROCEDURE "TRIGGER_CALL" (p_table_name IN VARCHAR2)
AUTHID CURRENT_USER
AS
l_sql VARCHAR2(4000);
l_dummy NUMBER;
l_trigger_name VARCHAR2(30);
BEGIN
-- Validate if a p_table_name is a valid object name
-- If you have access you can also use DBMS_ASSERT.SQL_OBJECT_NAME procedure
SELECT '1'
INTO l_dummy
FROM all_tables
WHERE table_name = UPPER(p_table_name);
l_trigger_name := p_table_name || '_trg';
l_sql :=
'CREATE OR replace TRIGGER ' || l_trigger_name ||
' BEFORE INSERT ON ' || p_table_name ||
' FOR EACH ROW
BEGIN
SELECT my_sequence.NEXTVAL
INTO :new.sno
FROM dual;
END;';
EXECUTE IMMEDIATE l_sql;
END;
/
CREATE TABLE my_test(sno NUMBER);
/
BEGIN
trigger_call('my_test');
END;
/
Important notes:
Usage of AUTHID CURRENT_USER eliminates the "insufficient privileges" problem. For reference see: Execute Immediate within a stored procedure keeps giving insufficient priviliges error
Because the dynamic sql simply concatenates the input parameter it needs to be validated to protect against SQL Injection. See also DBMS_ASSERT.
Because of point 2. I used table name to build trigger name.

Java call procedure oracle plsql return no data but in plsql return data

I have a function plsql, run function in plsql return cursor have data But i call this function in java problem return resultset falase Help me handling problem this
enter code here
This function plsql
FUNCTION get_canh_bao(
p_toolid in varchar2)
RETURN sys_refcursor IS
s varchar2(4000);
ptype varchar2(1000);
pday varchar2(1000);
psql varchar2(1000);
pcreate varchar2(1000);
re sys_refcursor;
pwhere varchar2(1000);
BEGIN
--
pwhere := '';
s := 'select b.TYPE_REPORT, b.DAY_NHAPLIEU, a.sql_cmd, a.name_createdate'
||' from cpcdata.tbl_config_nhaplieu a'
||' left join cpcdata.tbl_mainmenu b'
||' on a.tool_id = b.ID '
||' where b.show_all = 0 and b.flag = 1 and b.ID = :toolid';
execute immediate s INTO ptype, pday, psql, pcreate using p_toolid;
-- Tinh ngay canh bao
if (INSTR(psql,'where') > 0 ) then
pwhere := ' and ';
else
pwhere := ' where ';
end if;
s := psql ||pwhere||pcreate||' between :aDate AND :bDate';
CASE
WHEN ptype = 'day' THEN
s := psql ||pwhere|| ' to_char('||pcreate||',''dd/mm/yyyy'') = to_char(sysdate - '||pday||',''dd/mm/yyyy'')';
open re for s;
WHEN ptype = 'week' THEN
open re for s USING TRUNC (sysdate, 'iw'), TRUNC(sysdate, 'iw') + 7 - 1/86400- pday;
WHEN ptype = 'month' THEN
open re for s USING TRUNC (sysdate, 'mm'), to_date(LAST_DAY(TRUNC (sysdate, 'mm')) + 1 - 1/86400 - pday,'dd/mm/yyyy');
WHEN ptype = 'quy' THEN
open re for s USING TRUNC (sysdate, 'Q'), to_date(add_months(trunc(sysdate,'Q'),3)- 1 - pday, 'dd/mm/yyyy');
WHEN ptype = 'year' THEN
open re for s USING TRUNC (sysdate , 'YEAR'), to_date(ADD_MONTHS(TRUNC (SYSDATE,'YEAR'),12) - 1 - pday, 'dd/mm/yyyy');
ELSE return null;
END CASE;
dbms_output.put_line(''||s);
RETURN re ;
exception when others then
declare
s_err varchar2(2000);
str varchar(2000);
c_err sys_refcursor;
begin
s_err := 'loi khi lay du lieu '|| sqlerrm;
str := 'select '||s_err||' from dual';
open c_err for str;
return c_err;
end;
END;
This is code java
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn =
DriverManager.getConnection("jdbc:oracle:thin:#***:**:**",
"***", "***");
System.out.println("Connect db success ! ");
ArrayList arr = new ArrayList();
String sql = "{? = call get_canh_bao(?)}";
CallableStatement cs = conn.prepareCall(sql);
cs.registerOutParameter(1, OracleTypes.CURSOR);
cs.setString(2, "502");
cs.executeQuery();
ResultSet rs = (ResultSet)cs.getObject(1);
System.out.println("------------ResultSet---------------"+rs.next());
while (rs.next()) {
System.out.println("a");
String[] str =
{"1" };
arr.add(str);
}
System.out.println("size="+arr.size());
Result when run code in java
Connect db success !
------------ResultSet---------------false
size=0
The problem is likely caused by one of the date conversions that uses an implicit date format.
Oracle does not have a "default" date format, the date format is always dependent on the client. Your Java client and database IDE likely have different defaults.
But don't fix the code by changing the client settings. Instead, clean up the date functions and remove all date to character conversions.
In general, when working with dates, TO_DATE and TO_CHAR should almost always be avoided. If a date needs to be manipulated, there is almost surely a date function
that does not require a conversion. And dates should always be stored as dates, so you should not need to convert back and forth from the table.
The biggest problem is probably this:
pcreate varchar2(1000);
Change that to a date. If for some reason a.name_createdate is a string, then at least make the conversion explicit.
You're populating pcreate (a string) from tbl_config_nhaplieu.name_createdate without specifying a format, so (assuming it is a date column) it is possible that the format could be different within the Java client environment, e.g. if it defaults to mm/dd/yyyy or dd-mon-yyyy instead of dd/mm/yyyy.
Later you compare it directly to dates:
s := psql || pwhere || pcreate || ' between :aDate and :bDate';
but without quoting, so you'll get a query like this:
where 01/02/2016 between :aDate and nDate
Elsewhere you convert it back to a date assuming dd/mm/yyyy format (which you didn't specify when you encoded it as a string earlier, so there's no reason it should match that format):
s := psql || pwhere || ' to_char(' || pcreate || ',''dd/mm/yyyy'') = to_char(sysdate - ' || pday || ',''dd/mm/yyyy'')';
but it's not quoted there either, so you'll get something like this:
where to_char(01/02/2016,'dd/mm/yyyy') = to_char(sysdate - 3,'dd/mm/yyyy')
which will fail.
Then there's this:
to_date(last_day(trunc(sysdate,'mm')) + 1 - 1 / 86400 - pday, 'dd/mm/yyyy')
which may not give the result you expect. For example:
select to_date(last_day(trunc(sysdate,'mm')) + 1 - 1 / 86400 - 0, 'dd/mm/yyyy') as test
from dual;
which gives me 31-JUL-2016 in SQL*Plus and SQL Developer but 31/07/0016 in PL/SQL Developer, due to different nls_date_parameter settings.
As Jon said, you need to clean up all of the date handling.

How to use SQL Case in Group by Clause?

I'm using SQL Case in my select and in group by clause and I'm working in JAVA. Whenever I execute my java program it says:
Column 'dbo.JOHN_Dashboard.Log_Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
My Query is:
SELECT EP.Site_Code AS [Site_Code], DB.[Site] AS [Site], DB.[Utility] AS [Utility],
CASE ? WHEN 'Raw' THEN dateadd(mi,datediff(mi,0,DB.[log_date]),0)
WHEN 'Hour' THEN dateadd(hh,datediff(hh,0,DB.[log_date]),0)
WHEN 'Day' THEN dateadd(dd,datediff(dd,0,DB.[log_date]),0)
WHEN 'Week' THEN dateadd(wk,datediff(wk,0,DB.[log_date]),0)
WHEN 'Month' THEN dateadd(mm,datediff(mm,0,DB.[log_date]),0)
WHEN 'Year' THEN dateadd(yy,datediff(yy,0,DB.[log_date]),0)
ELSE DB.[log_date]
END AS [log_date],
SUM(CASE WHEN DB.[value] >= 0 THEN DB.[value] ELSE 0 END) AS [value],
SUM(CASE WHEN DB.[Cost] >=0 THEN DB.[cost] ELSE 0 END) AS [Cost],
SUM(CASE WHEN DB.[CO2] >=0 THEN DB.[CO2] ELSE 0 END) AS [CO],
MT.[Meter_type_name] AS [Meter Type],
MN.[Meter_Name] AS [Meter Name],
U.[Unit_Name] AS [Units],
EP.EnergyPoint_ID AS [Meter_ID],
EP.Parent_ID AS [Parent],
EP.Meter_Description AS [Meter_Description]
FROM [dbo].[JOHN_Dashboard] DB
INNER JOIN [dbo].[EnergyPoints] EP ON DB.[EnergyPoint_ID] = EP.[EnergyPoint_ID]
INNER JOIN [dbo].[Meter_Types] MT ON MT.[Meter_Type_ID] = EP.[Meter_Type_ID]
INNER JOIN [dbo].[Meter_Names] MN ON MN.[Meter_Name_ID] = EP.[Meter_Name_ID]
INNER JOIN [dbo].[Units] U ON U.[Unit_ID] = EP.[Unit_id]
WHERE [log_date] >= ? AND [Log_Date] < DATEADD(DAY, 1, ?)
AND ( ? IS NULL OR EP.Energypoint_ID = ?)
GROUP BY EP.Site_Code, DB.[Site], DB.[Utility], MT.[Meter_type_name],
MN.[Meter_Name], U.[Unit_Name], EP.[EnergyPoint_ID],
EP.[Parent_ID], EP.[Meter_Description],
CASE ? WHEN 'Raw' THEN dateadd(mi,datediff(mi,0,DB.[log_date]),0)
WHEN 'Hour' THEN dateadd(hh,datediff(hh,0,DB.[log_date]),0)
WHEN 'Day' THEN dateadd(dd,datediff(dd,0,DB.[log_date]),0)
WHEN 'Week' THEN dateadd(wk,datediff(wk,0,DB.[log_date]),0)
WHEN 'Month' THEN dateadd(mm,datediff(mm,0,DB.[log_date]),0)
WHEN 'Year' THEN dateadd(yy,datediff(yy,0,DB.[log_date]),0)
ELSE DB.[log_date] END ;
The parameters i'm passing are:
'Week'
'2016-05-16'
'2016-05-22'
6044
6044
'Week'
Note: This query runs without error in SQL Management Studio.
As requested here is a reworked version of your code using a sub-query before grouping. Since I don't have your database I can't guarantee that I have everything exactly right but give this a try.
I recommend always using a sub-query when your group by has complicated logic that will be repeated in the select. Some people would probably drop the second criteria and just say whenever the group by has complicated logic.
SELECT sub.Site_Code, sub.[Site], sub.[Utility], sub.[Meter Type],
sub.[log_date],
SUM(sub.[value]) as [value],
SUM(sub.[Cost]) as [cost],
SUM(sub.[CO]) as [CO],
sub.[Meter Name], sub.[Units], sub.[Meter_ID],
sub.[Parent], sub.[Meter_Description]
FROM (
SELECT EP.Site_Code AS [Site_Code], DB.[Site] AS [Site], DB.[Utility] AS [Utility],
CASE ? WHEN 'Raw' THEN dateadd(mi,datediff(mi,0,DB.[log_date]),0)
WHEN 'Hour' THEN dateadd(hh,datediff(hh,0,DB.[log_date]),0)
WHEN 'Day' THEN dateadd(dd,datediff(dd,0,DB.[log_date]),0)
WHEN 'Week' THEN dateadd(wk,datediff(wk,0,DB.[log_date]),0)
WHEN 'Month' THEN dateadd(mm,datediff(mm,0,DB.[log_date]),0)
WHEN 'Year' THEN dateadd(yy,datediff(yy,0,DB.[log_date]),0)
ELSE DB.[log_date]
END AS [log_date],
CASE WHEN DB.[value] >= 0 THEN DB.[value] ELSE 0 END AS [value],
CASE WHEN DB.[Cost] >=0 THEN DB.[cost] ELSE 0 END AS [Cost],
CASE WHEN DB.[CO2] >=0 THEN DB.[CO2] ELSE 0 END AS [CO],
MT.[Meter_type_name] AS [Meter Type],
MN.[Meter_Name] AS [Meter Name],
U.[Unit_Name] AS [Units],
EP.EnergyPoint_ID AS [Meter_ID],
EP.Parent_ID AS [Parent],
EP.Meter_Description AS [Meter_Description]
FROM [dbo].[JOHN_Dashboard] DB
INNER JOIN [dbo].[EnergyPoints] EP ON DB.[EnergyPoint_ID] = EP.[EnergyPoint_ID]
INNER JOIN [dbo].[Meter_Types] MT ON MT.[Meter_Type_ID] = EP.[Meter_Type_ID]
INNER JOIN [dbo].[Meter_Names] MN ON MN.[Meter_Name_ID] = EP.[Meter_Name_ID]
INNER JOIN [dbo].[Units] U ON U.[Unit_ID] = EP.[Unit_id]
WHERE [log_date] >= ? AND [Log_Date] < DATEADD(DAY, 1, ?)
AND ( ? IS NULL OR EP.Energypoint_ID = ?)
) sub
GROUP BY sub.Site_Code, sub.[Site], sub.[Utility], sub.[Meter Type],
sub.[Meter Name], sub.[Units], sub.[Meter_ID],
sub.[Parent], sub.[Meter_Description], sub.[log_date];

Commit in PLSQL loop for update

I am using the below function in my java program to copy a column from temporary table to main table.
FUNCTION TEST(TBL_NAME VARCHAR2, TMP_TBL_NAME VARCHAR2, ID_COL VARCHAR2, REQ_COL VARCHAR2, BATCH_SIZE NUMBER) RETURN NUMBER AS
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM ' || TMP_TBL_NAME INTO TOTAL_RECORDS;
OFFSET := 0;
WHILE OFFSET < TOTAL_RECORDS
LOOP
MAX_RESULTS := OFFSET + BATCH_SIZE;
EXECUTE IMMEDIATE 'SELECT ' || ID_COL || ', ' || REQ_COL || ' FROM ' || TMP_TBL_NAME || ' WHERE SEQ_NBR BETWEEN :OFFSET AND :MAX_RESULTS' BULK COLLECT INTO SEQ_IDS, REQ_COL_VALUESS USING OFFSET, MAX_RESULTS;
FORALL IND IN SEQ_IDS.FIRST .. SEQ_IDS.LAST
EXECUTE IMMEDIATE 'UPDATE ' || TBL_NAME || ' SET ' || REQ_COL || ' = :REQ_COL_VAL WHERE ' || ID_COL || ' = :ID_COL_VAL' USING REQ_COL_VALUESS(IND), SEQ_IDS(IND);
OFFSET := MAX_RESULTS;
COMMIT;
END LOOP;
RETURN 0;
EXCEPTION
WHEN OTHERS THEN
RAISE CUST_EXCEPTION;
END;
Expected result is when I am running with a batch_size of 100000, for each commit 100000 records have to be updated as id_col I used above is primary key. After running the java program, in middle when I am checking for updates in main table I am able to see that records of batches 6469 or 80148 like that are being updated.
There are about 10 million records in temp table. If I remove the forall update statement I am iterating over the data in proper batch size.
Can any clarify me on why this is happening
1) How many records do you have in your temporary tables?
2) Why you don't use sys_refcursor and bulk collect with limit ?
declare
v_cursor sys_refcursor;
res1 sys.DBMS_DEBUG_VC2COLL; -- - predefined collection in oracle
res2 sys.DBMS_DEBUG_VC2COLL;
v_batch_size pls_integer := 50;
begin
open v_cursor for 'Select 1,2 from dual connect by level < 10000';
loop
fetch v_cursor bulk collect into res1,res2 limit v_batch_size;
exit when res1.count =0;
dbms_output.put_line(res1.count);
-- forall ind in res1.first .. res1.last loop e.g
-- commit;
end loop;
close v_cursor;
end;
-- first iteration offset= 0 , max_result = 10
-- v_batch_size = 10
-- offset := 0
-- MAX_RESULTS := 10
select seg from ( Select level seg from dual connect by level < 1000) where seg between 0 and 10;
-- secound iteration
-- v_batch_size = 10
-- offset := 10
-- MAX_RESULTS := 20
select seg from ( Select level seg from dual connect by level < 1000) where seg between 10 and 20;

Categories