Need a procedure or a pl/sql block
Dear all,
I have a 2tables emp_address, address as below:
create table emp_address(emp_id varchar2(10),address varchar2(100));
Insert into EMP_ADDRESS
(EMP_ID, ADDRESS)
Values
('101', 'street1 fremont CA 94538');
Insert into EMP_ADDRESS
(EMP_ID, ADDRESS)
Values
('102', 'street2 fremont CA 94537');
COMMIT;
create table address(emp_id varchar2(10),street varchar2(20),city varchar2(15),state varchar2(10),zip varchar2(10));
The data in emp_address is as below:
emp_id address
101 street1 fremont CA 94538
102 street2 fremont CA 94537
now i have to read the data from emp_address and split the data of address column and save that data into address table like as below
emp_id street city state zip
101 street1 fremont ca 94538
102 street2 fremont ca 94537
So i need to write a procedure to get this. i am very new to Pl/sql. Could any one can help me to get this.
Thanks in adavnce
try out this,
create or replace procedure address as
Cursor c1 is select * from emp_address;
Begin
for r1 in c1 loop
insert into address values(r1.emp_id,substr(r1.address,1,instr(r1.address,' ',1,1))
,substr(r1.address,instr(r1.address,' ',1,1),instr(r1.address,' ',1,2)-instr(r1.address,' ',1,1))
,substr(r1.address,instr(r1.address,' ',1,2),instr(r1.address,' ',1,3)-instr(r1.address,' ',1,2))
,substr(r1.address,instr(r1.address,' ',1,3)));
end loop;
End;or as simple SQL stmt
insert into address values(emp_id,substr(address,1,instr(address,' ',1,1))
,substr(address,instr(address,' ',1,1),instr(address,' ',1,2)-instr(address,' ',1,1))
,substr(address,instr(address,' ',1,2),instr(address,' ',1,3)-instr(address,' ',1,2))
,substr(address,instr(address,' ',1,3)));
Similar Messages
-
Temporary table in a pl/SQL block
Hi all. I am in the process of learning PL/SQL and right now I focusing on Temporary Tables & PL/SQL blocks. without going into great detail I have created a cursor for loop that will retrive records from a table based on my criteria. I now need to insert this information into a temporary table. I am somewhat familiar on the usage of a temporary table by itself but I am confused by its usage in the PL/SQL block itself. For example, does it need to be declared?
pl/SQl block or PL/SQl table(associate array) ?
this example will help, if i got is correct
SQL> declare
2 cur_emp sys_refcursor;
3 type t_obj is record( empno number, ename varchar2(25));
4 type t_tab is table of t_obj index by binary_integer;
5 tt t_tab;
6 begin
7 open cur_emp for
8 select empno,ename from emp where deptno=10;
9 loop
10 fetch cur_emp BULK collect into tt;
11 exit when cur_emp%notfound;
12 end loop;
13 for i in 1..tt.count loop
14 dbms_output.put_line('empno :' ||tt(i).empno||' ename :'||tt(i).ename);
15 end loop;
16 end;
17 /
empno :7782 ename :CLARK
empno :7839 ename :KING
empno :7934 ename :MI_LL_ER
PL/SQL procedure successfully completed. -
Why named parameter can't be used multiple times in PL/SQL block in JDBC
with the following PL/SQL block, when I run int in JDBC, I get an error,
it says, The number of parameter names does not match the number of registered parameters.
if all named parameters are used only once, then my program works fine.
My old program uses Oracle Forms to run the attached PL/SQL block correctly, I just want to run them in JDBC without more efforts, I don't want to rewrite all PL/SQL blocks.
Does oracle driver support this case? why the PL/SQL block can work in Oracle Forms but failed in JDBC?
Can we have an another solutions to avoid rewriting the PL/SQL block to stored procedure?
if I use following SQL:
BEGIN if :q is null then :q := 'X'; else :q := 'Y'; end if; END;
, Using java program:
import java.sql.*; public class RunPLSQLBlock { public static void main(String s[]) throws SQLException { String URL = "jdbc:oracle:thin:@192.168.11.199:1521:TIBSTEST"; Connection con = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); con = (Connection) DriverManager.getConnection(URL, "FBP1DEV", "FBP1DEV"); String SQL = "BEGIN if :q is null then :q := 'X'; else :q := 'Y'; end if; END;"; CallableStatement stmt = con.prepareCall(SQL); stmt.registerOutParameter("q", Types.VARCHAR); stmt.setString("q", "A"); stmt.execute(); } catch (Exception e) { e.printStackTrace(); } finally { if (con != null) { con.close(); } } } }
in the coding, only "q" registered, I got:
java.sql.SQLException: The number of parameter names does not match the number of registered praremeters at oracle.jdbc.driver.OracleSql.setNamedParameters(OracleSql.java:314) at oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:10096) at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:5693) at RunPLSQLBlock.main(RunPLSQLBlock.java:28)
now, tried to register 3 indexes, changed fragments are below.
import java.sql.*; public class RunPLSQLBlock { public static void main(String s[]) throws SQLException { String URL = "jdbc:oracle:thin:@192.168.11.199:1521:TIBSTEST"; Connection con = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); con = (Connection) DriverManager.getConnection(URL, "FBP1DEV", "FBP1DEV"); String SQL = "BEGIN if :q is null then :q := 'X'; else :q := 'Y'; end if; END;"; CallableStatement stmt = con.prepareCall(SQL); stmt.registerOutParameter(1, Types.VARCHAR); stmt.registerOutParameter(2, Types.VARCHAR); stmt.registerOutParameter(3, Types.VARCHAR); stmt.setString(1, "A"); stmt.execute(); } catch (Exception e) { e.printStackTrace(); } finally { if (con != null) { con.close(); } } } }
now error changed to:
java.sql.SQLException: ORA-01006: bind variable does not exist at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:457) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:400) at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:926) at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:476) at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:200) at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:543) at oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:208) at oracle.jdbc.driver.T4CCallableStatement.executeForRows(T4CCallableStatement.java:1416) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1757) at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4372) at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:4595) at oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:10100) at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:5693) at RunPLSQLBlock.main(RunPLSQLBlock.java:26)
, now tried register only 1 position like below,
CallableStatement stmt = con.prepareCall(SQL); stmt.registerOutParameter(1, Types.VARCHAR); stmt.setString(1, "A"); stmt.execute();
, it says:
java.sql.SQLException: Missing IN or OUT parameter at index:: 2 at oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:2177) at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4356) at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:4595) at oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:10100) at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:5693) at RunPLSQLBlock.main(RunPLSQLBlock.java:26)
, now let try a OK case, which use all named parameters only once. coding like below, SQL and Java listed below.
BEGIN if :q is null then :r := 'X'; else :s := 'Y'; end if; EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END;
import java.sql.*; public class RunPLSQLBlock { public static void main(String s[]) throws SQLException { String URL = "jdbc:oracle:thin:@192.168.11.199:1521:TIBSTEST"; Connection con = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); con = (Connection) DriverManager.getConnection(URL, "FBP1DEV", "FBP1DEV"); String SQL = "BEGIN if :q is null then :r := 'X'; else :s := 'Y'; end if; END;"; CallableStatement stmt = con.prepareCall(SQL); stmt.registerOutParameter("q", Types.VARCHAR); stmt.registerOutParameter("r", Types.VARCHAR); stmt.registerOutParameter("s", Types.VARCHAR); stmt.setString("q", "A"); stmt.execute(); System.out.println("Q :" + stmt.getString("q")); System.out.println("R :" + stmt.getString("r")); System.out.println("S :" + stmt.getString("s")); } catch (Exception e) { e.printStackTrace(); } finally { if (con != null) { con.close(); } } } }
, the case give us the following output:
Q :A R :null S :Y
2nd part, I also tried another scheme, to use 'execute immediate', test code attached below, it also have errors.
begin execute immediate 'begin if :q is null then :q := ''X''; else :q := ''Y''; :r := ''Z''; end if; end;' using in out :q, out :r; end;
, Java Code:
import java.sql.*; public class RunDynamicSQL { public static void main(String s[]) throws SQLException { String URL = "jdbc:oracle:thin:@192.168.11.199:1521:TIBSTEST"; Connection con = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); con = (Connection) DriverManager.getConnection(URL, "FBP1DEV", "FBP1DEV"); String SQL ="begin execute immediate 'begin if :q is null then :q := ''X''; else :q := ''Y''; :r := ''Z''; end if; end;' using in out :q, out :r; end;"; CallableStatement stmt = con.prepareCall(SQL); stmt.registerOutParameter("q", Types.VARCHAR); stmt.registerOutParameter("r", Types.VARCHAR); stmt.setString("q", "A"); stmt.execute(); System.out.println("Q :" + stmt.getString("q")); System.out.println("R :" + stmt.getString("r")); } catch (Exception e) { e.printStackTrace(); } finally { if (con != null) { con.close(); } } } }
, the output is, we can find when parameter 'q' is IN OUT mode, we can't get its final value:
Q :null R :Z
, now I tried my workaround, it works fine by using a temporary variable, now my named parameter is split to 2 roles, one is for IN, another is for OUT, now I can get final out value.
declare q clob; r clob; begin q := ?; r := ?; execute immediate 'begin if :q is null then :q := ''X''; else :q := ''Y''; :r := ''Z''; end if; end;' using in out q, out r; ? := q; ? := r; end;
, my test java code,
import java.sql.*; public class RunDynamicSQL { public static void main(String s[]) throws SQLException { String URL = "jdbc:oracle:thin:@192.168.11.199:1521:TIBSTEST"; Connection con = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); con = (Connection) DriverManager.getConnection(URL, "FBP1DEV", "FBP1DEV"); String SQL ="declare q clob;r clob; begin q := ?; r := ?; execute immediate 'begin if :q is null then :q := ''X''; else :q := ''Y''; :r := ''Z''; end if; end;' using in out q, out r; ? := q; ? := r; end;"; CallableStatement stmt = con.prepareCall(SQL); stmt.registerOutParameter(3, Types.VARCHAR); stmt.registerOutParameter(4, Types.VARCHAR); stmt.setString(1, "A"); stmt.setString(2, "A"); stmt.execute(); System.out.println("Q :" + stmt.getString(3)); System.out.println("R :" + stmt.getString(4)); } catch (Exception e) { e.printStackTrace(); } finally { if (con != null) { con.close(); } } } }
, the output is expected,
Q :Y R :Z
Database:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
JDBC Driver, extracted from ojdbc6_g.jar/META-INF/MANIFEST.MF :
Created-By: 1.5.0_30-b03 (Sun Microsystems Inc.)
Implementation-Vendor: Oracle Corporation
Implementation-Title: JDBC debug
Implementation-Version: 11.2.0.3.0
Repository-Id: JAVAVM_11.2.0.3.0_LINUX_110823
Specification-Vendor: Sun Microsystems Inc.
Specification-Title: JDBC
Specification-Version: 4.0
Main-Class: oracle.jdbc.OracleDriver
JDK:
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) Client VM (build 21.0-b17, mixed mode, sharing)
Edited by: jamxval on 2013-3-22 2:01PM (UTC+08:00), Give full test java program and SQL, added environment/API level; Attached another problem.
Edited by: jamxval on 2013-3-26 17:57 (UTC +08), Adjust code styleHi, thanks for your response, now I see, the named parameter is for stored procedure only, for PL/SQL block we name it placeholder name.
After cast my java.sql.CallableStatement to oracle.jdbc.OracleCallableStatement, I can find setStringAtName,
now, I have only one question:I can't find corresponding methods for registerOutputParameter, how we fetch output value?
I tried to callableStatement.getString("q"); it reports errors, but there are no ordinal binding in my source code, does placeholder names doesn't support OUT mode?
Java:
CallableStatement stmt = con.prepareCall("BEGIN if :q is null then :r := 'X'; else :s := 'Y'; end if; END;");
oracle.jdbc.OracleCallableStatement call = (oracle.jdbc.OracleCallableStatement) stmt;
call.registerOutParameter("q", Types.VARCHAR);
call.registerOutParameter("r", Types.VARCHAR);
call.registerOutParameter("s", Types.VARCHAR);
call.setStringAtName("q", "A");
call.setStringAtName("r", "A");
call.setStringAtName("s", "A");
call.execute();
System.out.println("Q :" + call.getString("q"));
</Java>
<output>
java.sql.SQLException: 不允许的操作: Ordinal binding and Named binding cannot be combined!
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.OracleCallableStatement.getString(OracleCallableStatement.java:2834)
at RunPLSQLBlock.main(RunPLSQLBlock.java:33)
</output>by the way, in my below-mentioned SQL 'problematic', when my code uses 'execute immediate' and use placeholder names in IN OUT mode, we always get NULL value (i.e. ':q'), but we can get final value of ':r' when ':r' is OUT mode only; now I get a workaround attached in below-mentioned 'my workaround' block, which split the IN OUT roles to 2 parts, it can work now;
It seems that the difference between 'problematic' and 'my workaround' imply that there are something work unexpectedly when the driver process the placeholder names, because 'my workaround' and ':r in problematic case' make sure the 'execute immediate' returned output values correctly, unluckly driver layer can't get return values.
<SQL name = 'problematic'>
begin
execute immediate 'begin if :q is null then :q := ''X''; else :q := ''Y''; :r := ''Z''; end if; end;'
using in out :q, out :r;
end;
</SQL>
<SQL name='my workaround'>
declare
q clob;
r clob;
begin
q := ?;
r := ?;
execute immediate 'begin if :q is null then :q := ''X''; else :q := ''Y''; :r := ''Z''; end if; end;' using in out q, out r;
? := q;
? := r;
end;Edited by: EJP on 26/03/2013 14:14 -
PL/SQL block to populate a table
Hello Gurus,
Need help to write a pl/sql block as per below:
1. Write a PL/SQL block which will populate the RESULTS table as described below. Consider performance implications (specifically where would you commit the queries) as we are dealing with millions of records.
The PL/SQL will:
- insert into the RESULTS table each customer id, and the number of unique products purchased by that customer.
- update the recently_purchased column of the customer table to 'Y' (yes if they have purchased a product in the last 12 months) or 'N' (if they have not purchased a product in the last 12 months).
Listed below are the tables & definitions:
table: CUSTOMER
columns:
customer_id NUMBER,
customer_name VARCHAR2(100),
recently_purchased VARCHAR2(1) -- 'Y' or 'N'
table: CUST_PRODUCTS
columns:
product_id NUMBER,
customer_id NUMBER,
date_purchased DATE
table: RESULTS
columns: customer_id NUMBER, product_count NUMBER
Thanks a lot..Hi Guys,
I've tried this to my best but I feel like something's definately wrong with my update statement.
Please help..
--create customer table
create table customer (
customer_id number(6),
customer_name varchar2(100),
recently_purchased varchar2(1));
-- describe to see if it is created as required
desc customer
--populate customer table with random values
Begin
For i in 1..20
Loop
Insert into customer(customer_id,customer_name,recently_purchased)
values(i, dbms_random.string('U',5),'N');
If mod(i, 100000) = 0 then
Commit;
End if;
End loop;
End;
--create cust_products table
create table cust_products
(product_id number (6),
customer_id number(6),
date_purchased date);
--describe to see if table is created as required
desc cust_products
--populate cust_products with custome_id 1 to 10 and dates
Begin
For i in 1..20
Loop
Insert into cust_products
values(dbms_random.value(555,999),i,add_months('04-Nov-08',i));
If mod(i, 100000) = 0 then
Commit;
End if;
End loop;
End;
select * from cust_products
--update customer table as required
Begin
For i in 1..10
Loop
update customer set recently_purchased = 'Y';
commit;
update customer C set recently_purchased = 'N' where exists (select date_purchased from cust_products P where C.customer_id = P.customer_id );
commit;
End loop;
End;
--Insert into results table
select customer_id,count(product_id)
from cust_products
group by customer_id
Edited by: user497841 on Feb 4, 2010 2:12 PM -
Accepting user input and executing a PL/SQL block using it
Hi All,
I am working on a requirement wherein I have to accept values from the user for the various arguments to be supplied to a PL/SQL block and then execute it using these values. For now, I am using the following logic:
PROMPT Enter value for the Category
ACCEPT cCategory CHAR PROMPT 'Category:'
DECLARE
cCategry CHAR(1) := '&cCategory';
BEGIN
DBMS_OUTPUT.PUT_LINE('The value of the Category as entered by you is' || cCategory);
END;
PROMPT Press y if you want to proceed with the current values, or press n if you want to re-enter the values
ACCEPT cChoice CHAR Prompt 'Enter y or n:'
DECLARE
cCategry CHAR(1) := '&cCategory';
sErrorCd VARCHAR2(256);
sErrorDsc VARCHAR2(256);
BEGIN
IF '&cChoice' = 'y'
THEN
DBMS_OUTPUT.PUT_LINE('Starting with the process to execute the stored proc');
--- schema1.package1.sp1(cCategry, sErrorCd, sErrorDsc);
--- DBMS_OUTPUT.PUT_LINE('Error Code :' || sErrorCd);
--- DBMS_OUTPUT.PUT_LINE(' Error Description :' || sErrorDsc);
ELSIF '&cChoice' = 'n'
THEN
Now I want that the proc again start executing in the loop from the 1st line i.e. PROMPT Enter value for the Category. However i see that this is not possible to do that PROMPT statements and accepting user inputs execute only on the SQL prompt and not inside a PL/SQL block.
Is there an alternate method to establish this?
Thanks in advance.Hi,
You can write a genric procedure to achive the desired output. Pass 'Y' or 'N' in the procedure.
Call that procedure in simple pl/sql block during runtime using substituton operator.
For ex
create or replace procedure p1(category_in in varchar2)
IS
BEGIN
if (category_in='Y')
then
prcdr1()
/** Write your logic here ***/
elsif(category_in='N') then
prcdr2()
/** write your logic here***/
end if;
exception
/***write the exception logic ***/
end p1;
Begin
p1('&cat');
end;Regards,
Achyut K
Edited by: Achyut K on Aug 6, 2010 5:20 AM -
Need to refresh materialized view from procedure and pl/sql block
Hi,
I need to refresh materialized view (complete refresh)from procedure and pl/sql block .can some one help.
MV name:MV_DGN_TEST_SESSION
Thanks,
Rajasekhardbms_mview.REFRESH ('MV_DGN_TEST_SESSION', 'C');Regards,
Mahesh Kaila
Edited by: user4211491 on Dec 1, 2009 10:41 PM -
Stored Procedure Vs PL-SQL Block
Hi,
I came across an interesting problem last week. Fortunately, I was able to solve it or find an acceptable workaround for myself. But wanted to get some clarification from the experts. So posting it here.
Also, I am new to Orcle, so please excuse any shortcomings in the post.
My data model has following tables-
TABLE_PARENT (ID, other columns)
TABLE_CHILD (ID, other columns, PARENT_ID_FK)
Here, ID is the primary key column for the respective tables; PARENT_ID_FK is the foreign key referencing the ID column from the TABLE_PARENT.
I created a stored procedure programmatically (using MS Excel) to insert records in the two tables. The stored procedure has insert statements for an indefinite number of records in the parent table and for every such record, there's a corresponding record inserted in the child table. Here's the sample code.
BEGIN
/*first record*/
parent_id := MY_SEQUENCE_GENERATOR.NEXTVAL;
INSERT INTO TABLE_PARENT(ID, other columns) VALUES (parent_id, other values);
INSERT INTO TABLE_CHILD(ID, other values,parent_id );
/*second record*/
parent_id := MY_SEQUENCE_GENERATOR.NEXTVAL;
INSERT INTO TABLE_PARENT(ID, other columns) VALUES (parent_id, other values);
INSERT INTO TABLE_CHILD(ID, other values,parent_id );
/*third record*/
parent_id := MY_SEQUENCE_GENERATOR.NEXTVAL;
INSERT INTO TABLE_PARENT(ID, other columns) VALUES (parent_id, other values);
INSERT INTO TABLE_CHILD(ID, other values,parent_id );
/*and so on*/
END
When I run this stored procedure, I keep getting following exception intermittently-
ORA-02291: integrity constraint violated-parent key not found tips.
My thinking is that it comes because the insert statements are executing ahead of turn of the parent_id assignment statement. And this is happening possibly because of some parallelism that is taking place during the execution of the stored procedure, or, some sort of optmization that the DB server does (though erroneously) when it compiles the stored procedure.
I tried out everything that I could think of but it didn't go away. Finally, when I executed the same set of statements as a PL-SQL block, it worked fine.
To understand it better, I am looking for clarification on the following questions.
1) Why does the exception come with stored procedure but not with PL-SQL block? Is my reasoning given above correct (parallelism or some sort of optimization coming into play)?
2) If it is due to parallelism, how to run a Oracle stored procedure with defree of prallelism set to 1?
3) If it is due to optimization done by the compiler, how to instruct the compiler to not do any such optimization. Also, in any case, isn't it an error to optimize but lose program semantics?
4) Another question related to the same piece of work I have is to use transactions in the PL-SQL block, I had to explicitly COMMIT/ROLLBACK it in the code. In whatever references I had read, it was said that by default the transaction begins with BEGIN statement and commits with END. Also, it seems to work with a Stored Proedure though. So is it that a PL_SQL block needs explicity call to COMMIT/ROLLBACK to achive transactions but stored procedures do not?
Any inputs/clarifications will be much appreciated.
Thank you
NeeleshOk, your last couple of paragraphs were helpful. Here're the details that were missing in my earlier post.
- I am on Oracle 10.2.0.
- Table definitions-
CREATE TABLE "MYUSER"."TABLE_PARENT"
*( "ID" NUMBER(19,0) NOT NULL ENABLE,*
* "NAME" VARCHAR2(30),*
* "DESCRIPTION" VARCHAR2(80),*
* "RULETYPE" NUMBER(10,0) NOT NULL ENABLE,*
* "OPERATOR" NUMBER(10,0),*
* "MININTERCEPT" FLOAT(126),*
* "PRIORITY" NUMBER(10,0),*
* "PENALTY" NUMBER(10,0),*
* "STATUS" NUMBER(10,0),*
* PRIMARY KEY ("ID")*
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 131072 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS" ENABLE,
*) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING*
STORAGE(INITIAL 131072 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS"
CREATE TABLE "MYUSER"."TABLE_CHILD"
*( "ID" NUMBER(19,0) NOT NULL ENABLE,*
* "WEIGHT" NUMBER(19,0),*
* "PARENTID_FK" NUMBER(19,0),*
* PRIMARY KEY ("ID")*
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 131072 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS" ENABLE,
* CONSTRAINT "FK3A78BF1E6A9DCE51" FOREIGN KEY ("PARENTID_FK")*
* REFERENCES "MYUSER"."TABLE_PARENT" ("ID") ENABLE*
*) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING*
STORAGE(INITIAL 131072 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS"
- The Stored procedure definition is-
CREATE OR REPLACE PROCEDURE LOAD_RULES_SP AS
ruleid NUMBER(19,0);
tempid NUMBER(19,0);
BEGIN
*/* First parent record */*
SELECT IDGENERATOR.NEXTVAL INTO ruleid FROM dual;
INSERT INTO TABLE_PARENT (ID, NAME, DESCRIPTION, RULETYPE, OPERATOR, MININTERCEPT, PRIORITY, penalty, STATUS) VALUES (ruleid, 'Rule 1',null,3,0,0,null,null,1);
*/* Corresponding child records */*
SELECT IDGENERATOR.NEXTVAL INTO tempid FROM dual;
INSERT INTO TABLE_CHILD (id, weight, PARENTID_FK)
VALUES (tempid, 0.2, ruleid);
SELECT IDGENERATOR.NEXTVAL INTO tempid FROM dual;
INSERT INTO TABLE_CHILD (id, weight, PARENTID_FK)
VALUES (tempid, 0.5, ruleid);
SELECT IDGENERATOR.NEXTVAL INTO tempid FROM dual;
INSERT INTO TABLE_CHILD (id, weight, PARENTID_FK)
VALUES (tempid, 0.3, ruleid);
*/* First parent record */*
SELECT IDGENERATOR.NEXTVAL INTO ruleid FROM dual;
INSERT INTO TABLE_PARENT (ID, NAME, DESCRIPTION, RULETYPE, OPERATOR, MININTERCEPT, PRIORITY, penalty, STATUS) VALUES (ruleid, 'Rule 1',null,3,0,0,null,null,1);
*/* Corresponding child records */*
SELECT IDGENERATOR.NEXTVAL INTO tempid FROM dual;
INSERT INTO TABLE_CHILD (id, weight, PARENTID_FK)
VALUES (tempid, 0.2, ruleid);
SELECT IDGENERATOR.NEXTVAL INTO tempid FROM dual;
INSERT INTO TABLE_CHILD (id, weight, PARENTID_FK)
VALUES (tempid, 0.5, ruleid);
SELECT IDGENERATOR.NEXTVAL INTO tempid FROM dual;
INSERT INTO TABLE_CHILD (id, weight, PARENTID_FK)
VALUES (tempid, 0.3, ruleid);
*/* And so on for a few parent records more */*
END;
Can you throw some light on the exception I was seeing now? Note that when I changed from stored procedure to an anonymous block, it worked fine.
One correction in my earlier post is that as the code snippet shows, there are multiple inserts in the child table for every record inserted in the parent one. -
Pl/sql block is too slow, should procedure a better option
Hi all,
how to tune A PL/SQL block that traverse cursors and fetch millions of records then execute inserts in different tables,
using execute immediate statement.
It's too slow and takes 10 hours to populate 40 tables having millions of records,
as i have to do some modifications in data so can not do it by CTAS,
i.e. a single sql statement.
Should i make a procedure, does it help .
Please help or suggest As i am New to PL/Sql
My code look like,
declare
cursor cur_table1 is
select field1,field2,field3,field4 from table1;
begin
for i in cur_table1
loop
execute immediate 'insert into table2 (field1,field2,field3,field4) '||
'select :1,field2,field3,field4 '||
' from table1 where field3= :2'
using i.field1||'_'||to_char(sysdate,'ddmmyyyy hh12:mi:ss',i.field1;
commit;
end if;
end;
Thanks and Regards,declare
cursor cur_projects is
select PROJECTID, PROJECTNAME, DESCRIPTION, DELETED, DELETINGDATE, ACTIVE, ADMINONLY, READONLY, SECURITYCLASS, PROJECTCONTACT, DEFAULTVERSION, DEFAULTSTARTPAGE, IMAGEPATH, MAXEXAMINEERRORS, LOCKTIMEOUT, MEMORYSAVINGLEVEL, PRELOADOBJECTS, PUBLICATIONSRCPROJNAME, CREATOR, CREATED, MODIFIER, MODIFIED from projects ;
cursor cur_projectversion(p_projectid projects.projectid%TYPE) is
select PROJECTID, PROJECTVERSIONID, PROJECTVERSIONNAME, DESCRIPTION, DELETED , DELETINGDATE, ACTIVE , ADMINONLY, READONLY, decode(EFFECTIVEDATE,null,trunc(sysdate),EFFECTIVEDATE) EFFECTIVEDATE, EXPIRATIONDATE, SECURITYCLASS, PROJECTCONTACT, DEFAULTVERSION, DEFAULTSTARTPAGE, IMAGEPATH, MAXEXAMINEERRORS, LOCKTIMEOUT, MEMORYSAVINGLEVEL, PRELOADOBJECTS, PUBLICATIONSRCPROJNAME, PUBLICATIONSRCPROJVERNAME, CREATOR, CREATED, MODIFIER, MODIFIED, PROFILELOADERCLASS /*, TRACKCHANGES */
from projectversions where PROJECTID=p_projectid ;
cursor cur_objects(p_projectid projects.projectid%TYPE,p_projectversionid projectversions.projectversionid%TYPE) is
select PROJECTID , PROJECTVERSIONID, OBJECTID , OBJECTKEY , PARENTID, KIND , NAME , TITLE , OWNER , CREATED, MODIFIER , MODIFIED , READY_TO_PUBLISH, LAST_PUBLISHED_DATE , LAST_PUBLISHER , EFFECTIVE_PUBLISHING_DATE , PUBLISHER , PUBLISHING_DATE /*, to_lob(scripttext) */ from OBJECTS where PROJECTID=p_projectid and PROJECTVERSIONID=p_projectversionid /*order by objectid */;
begin
for i in cur_projects
loop
dbms_output.put_line('PROJECTID => '||i.projectid);
dbms_output.put_line('_________________________________');
execute immediate 'insert into &TARGET_USER\.projects(locktimeout, memorysavinglevel , preloadobjects, projectid, projectname, description, deleted, deletingdate, active, adminonly, readonly, securityclass, projectcontact, defaultversion, defaultstartpage, imagepath, maxexamineerrors ) values (:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17) '
using i.locktimeout, i.memorysavinglevel, i.preloadobjects,i.projectid ,i.projectname , i.description , i.deleted , i.deletingdate , i.active , i.adminonly , i.readonly, i.securityclass, i.projectcontact , i.defaultversion, i.defaultstartpage , i.imagepath, i.maxexamineerrors;
for k in cur_projectversion(i.projectid)
loop
for l in cur_objects(k.projectid,k.projectversionid)
loop
cnt:=cnt+1;
select count(1) into object_exists from &TARGET_USER\.objects where objectid=l.objectid and projectversionid=1 and projectid=l.projectid;
if object_exists = 0
then
if l.objectid = 1 ------Book Object , objectid = 1 and parentid = 0
then
execute immediate 'INSERT INTO &TARGET_USER\.objects(PROJECTID,PROJECTVERSIONID,OBJECTID, OBJECTKEY,PARENTID,NAME, KIND,LAST_PUBLISHED_DATE,LAST_PUBLISHER,REVISIONID,DISPLAYORDER,READONLY,DELETED) values( :1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13)'
using l.PROJECTID, 1, l.OBJECTID,l.OBJECTKEY, 0 , l.NAME,l.KIND, '' , '' , '', 0, 'N', 'N';
else
select count(1) into object_parentid_exists from objects where objectid=l.parentid and projectversionid=1 and projectid=l.projectid;
if object_parentid_exists = 0 ---Set Parentid as 1
then
cnt_parentid_1:=cnt_parentid_1+1;
execute immediate 'INSERT INTO &TARGET_USER\.objects(PROJECTID,PROJECTVERSIONID,OBJECTID, OBJECTKEY,PARENTID,NAME, KIND,LAST_PUBLISHED_DATE,LAST_PUBLISHER,REVISIONID,DISPLAYORDER,READONLY,DELETED) values( :1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13)'
using l.PROJECTID, 1, l.OBJECTID,l.OBJECTKEY, 1 , l.NAME,l.KIND, '' , '' , '', 0, 'N', 'N';
else
execute immediate 'INSERT INTO &TARGET_USER\.objects(PROJECTID,PROJECTVERSIONID,OBJECTID, OBJECTKEY, PARENTID, NAME, KIND,LAST_PUBLISHED_DATE,LAST_PUBLISHER,REVISIONID,DISPLAYORDER,READONLY,DELETED) values( :1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13)'
using l.PROJECTID, 1, l.OBJECTID,l.OBJECTKEY,l.PARENTID,l.NAME,l.KIND, '' , '' , '', 0, 'N', 'N';
end if;
end if ;
end if;
execute immediate 'INSERT INTO &TARGET_USER\.objectversions( PROJECTID, OBJECTID, PROJECTVERSIONID ,VERSIONNAME,OBJECTVERSIONID, REVISIONID,DESCRIPTION, TITLE , OWNER, CREATED, MODIFIER, MODIFIED, READY_TO_PUBLISH , LAST_PUBLISHED_DATE, LAST_PUBLISHER, EFFECTIVEDATE, SCRIPTTEXT, REVIEWSTATUS, READONLY, PUBLISHED, DELETED ) '||
'SELECT PROJECTID, OBJECTID, 1, owner||:1, PROJECTVERSIONID , '''', '''', TITLE, OWNER, CREATED, MODIFIER, MODIFIED, ''N'', '''' , '''', :2 , to_lob(SCRIPTTEXT), '''', ''N'', ''N'', '''' '||
'FROM OBJECTS '||
'WHERE PROJECTID= :3 and PROJECTVERSIONID= :4 and OBJECTID= :5'
using '_'||TO_CHAR(k.EFFECTIVEDATE,'DDMMYYHHMISS'),k.EFFECTIVEDATE,l.projectid,l.projectversionid,l.objectid;
end loop;
dbms_output.put_line(cnt||' OBJECTS, OBJECTVERIONS POPULATED');
dbms_output.put_line(cnt_parentid_1||' DUMPED UNDER BOOK FOLDER ');
cnt_parentid_1:=0;
cnt:=0;
............ -
Need (procedure or function or sql query )for Email filter
Hi All,
in (procedure or function or sql query ) ,if i pass the a input parameter like (anbu@y or anbu@ or anbu@yahjjj ) ,i need to get output like [email protected] .
please give me code for this ...SQL> with t
2 as
3 (
4 select 'anbu@y' email from dual union all
5 select 'anbu@' from dual union all
6 select 'anbu@yahjjj' from dual
7 )
8 select email, regexp_replace(email, '@.*','@yahoo.com') email_new
9 from t
10 /
EMAIL
EMAIL_NEW
anbu@y
[email protected]
anbu@
[email protected]
anbu@yahjjj
[email protected] -
PL/SQL Block working fine but same code procedure is giving error.
Hi Experts,
I am executing procedure getting error ORA-27486: insufficient privileges
If It's PL/SQL block it's creating job classes.
Both the cases same user.
CREATE OR REPLACE PROCEDURE JOB_CLASS_PROC
AS
V_SQL VARCHAR2 (4000);
V_JOB_STEP VARCHAR2 (50);
BEGIN
-- Create Job Class if not exist
BEGIN
FOR i
IN (SELECT SNS.OWNER_NAME OWNER_NAME,
VDB.NAME
SNAME
FROM SCHEMA_NAMES SNS,
V$DATABASE VDB
WHERE OWNER_NAME NOT IN ('')
AND (OWNER_NAME || '_JOB_CLASS')
NOT IN
(SELECT JOB_CLASS_NAME FROM DBA_SCHEDULER_JOB_CLASSES))
LOOP
V_SQL :=
'BEGIN
DBMS_SCHEDULER.CREATE_JOB_CLASS
job_class_name => ''' || i.owner_name || '_JOB_CLASS'',
service => ''' || i.SNAME || ''',
comments => ''Job class for ' || i.owner_name || '''
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;';
EXECUTE IMMEDIATE V_SQL;
END LOOP;
END;
EXCEPTION
WHEN OTHERS
THEN
RAISE_APPLICATION_ERROR(-20001, V_JOB_STEP||' SQLERRM: ' || SQLERRM || ' SQLCODE: '|| SQLCODE);
END JOB_CLASS_PROC;
DECLARE
V_SQL VARCHAR2 (4000);
V_JOB_STEP VARCHAR2 (50);
BEGIN
-- Create Job Class if not exist
BEGIN
FOR i
IN (SELECT SNS.OWNER_NAME OWNER_NAME,
VDB.NAME
SNAME
FROM SCHEMA_NAMES SNS,
V$DATABASE VDB
WHERE OWNER_NAME NOT IN ('')
AND (OWNER_NAME || '_JOB_CLASS')
NOT IN
(SELECT JOB_CLASS_NAME FROM DBA_SCHEDULER_JOB_CLASSES))
LOOP
V_SQL :=
'BEGIN
DBMS_SCHEDULER.CREATE_JOB_CLASS
job_class_name => ''' || i.owner_name || '_JOB_CLASS'',
service => ''' || i.SNAME || ''',
comments => ''Job class for ' || i.owner_name || '''
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;';
EXECUTE IMMEDIATE V_SQL;
END LOOP;
END;
EXCEPTION
WHEN OTHERS
THEN
RAISE_APPLICATION_ERROR(-20001, V_JOB_STEP||' SQLERRM: ' || SQLERRM || ' SQLCODE: '|| SQLCODE);
END;
Why for same code procedure is giving error.
Please help me.
Thanks.Hi,
Then with the same grants how the below script is working.
If I put the below same script in Procedure it's not working.
DECLARE
V_SQL VARCHAR2 (4000);
V_JOB_STEP VARCHAR2 (50);
BEGIN
-- Create Job Class if not exist
BEGIN
FOR i
IN (SELECT SNS.OWNER_NAME OWNER_NAME,
VDB.NAME
SNAME
FROM SCHEMA_NAMES SNS,
V$DATABASE VDB
WHERE OWNER_NAME NOT IN ('')
AND (OWNER_NAME || '_JOB_CLASS')
NOT IN
(SELECT JOB_CLASS_NAME FROM DBA_SCHEDULER_JOB_CLASSES))
LOOP
V_SQL :=
'BEGIN
DBMS_SCHEDULER.CREATE_JOB_CLASS
job_class_name => ''' || i.owner_name || '_JOB_CLASS'',
service => ''' || i.SNAME || ''',
comments => ''Job class for ' || i.owner_name || '''
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;';
EXECUTE IMMEDIATE V_SQL;
END LOOP;
END;
EXCEPTION
WHEN OTHERS
THEN
RAISE_APPLICATION_ERROR(-20001, V_JOB_STEP||' SQLERRM: ' || SQLERRM || ' SQLCODE: '|| SQLCODE);
END;
Please help me.
Thanks. -
Need help with this pl/sql block
hi iam preparing for 1z0-001 exam..iam not able to figure out this .plz help
Which line in the following PL/SQL block will raise an exception?
1 TYPE emp_typ is RECORD (
emp_no VARCHAR2(20),
name scott.emp.name%TYPE);
2 emp_rec emp%ROWTYPE;
3 BEGIN
4 SELECT * INTO emp_rec FROM emp
WHERE emp_no=12;
5 emp_rec.emp_no := emp_seq.nextval;
6 INSERT INTO emp VALUES (emp_rec);
7 END;
1. Line 1
2. Line 2
3. Line 4
4. Line 6
ans:D. sybex text book
how is it possible??/
thank u
rajiv0. "DECLARE" is missing (or CREATE PROCEDURE...)
1a. emp_typ is declared but never used. Not strictly an error but suspicious.
1b. In the code, emp_no is a number but is declared here as a varchar2. Yuck.
2. fine.
3. fine.
4. fine.
5. You can't directly assign a sequence like this. It must be part of a sql statement.
6. Omit the parentheses around emp_rec. -
Can some one please tell me what is the problem in the below pl/sql block
Hi, I have problem with the following pl/sql block, I need this with bulk operation.
-- Assume the following scenario, we are validating dept (master) and emp(child) which are my temporary tables and updating the status back to
-- dept ( for all the validation errors, even if we have any validation at child it has to update the header record with error message),
-- upon successful validation insert the data into dept3, and emp3 interms of batches
-- I have give the sample example with dept and emp, but i have around 10 million records which has around 30-40 validations,
-- I would like to process them in terms of batches using bulk collection as this would do fast processing
-- Can some one please tell me how to insert them in terms of bulk with every set of 1000 records in each batch in this example,for every set of 1000 records
-- i need update batch id with unique number in dept table
-- with current data i can have 50 batches , I need to pass, deptno as parameter to my emp cursor.
-- can some one please tell me how to make this validation and insertion more efficient. so that while inserting the data for every batch it should insert batch id
-- Tried with LIMIT clause as well but not working
-- I am correcting the code as per your comments Request you to please suggest me so that I can correct , I am new to PL/sql, started learning now.
step - 1:
CREATE TABLE DEPT
(DEPTNO NUMBER(6) primary key,
DNAME VARCHAR2(25),
LOC VARCHAR2(23),
batch_id number );
INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK', null);
INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS', null);
INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO', null);
INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON', null);
step - 2:
declare
begin
for i in 1..50000 loop
insert into dept values(40+i, 'OPERATIONS'||i,'BOSTON'||i, null);
end loop;
commit;
exception
when others then
dbms_output.put_line('Exception occured:'||SQLERRM);
end;
step - 3:
create sequence emp_seq start with 1 increment by 1;
step - 4:
CREATE TABLE EMP
(EMPNO NUMBER(15) NOT NULL primary key,
ENAME VARCHAR2(20),
JOB VARCHAR2(20),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(6));
INSERT INTO EMP VALUES
(7369, 'SMITH', 'CLERK', 7902,
TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);
INSERT INTO EMP VALUES
(7499, 'ALLEN', 'SALESMAN', 7698,
TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30);
INSERT INTO EMP VALUES
(7521, 'WARD', 'SALESMAN', 7698,
TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30);
INSERT INTO EMP VALUES
(7566, 'JONES', 'MANAGER', 7839,
TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20);
INSERT INTO EMP VALUES
(7654, 'MARTIN', 'SALESMAN', 7698,
TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);
INSERT INTO EMP VALUES
(7698, 'BLAKE', 'MANAGER', 7839,
TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30);
INSERT INTO EMP VALUES
(7782, 'CLARK', 'MANAGER', 7839,
TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10);
INSERT INTO EMP VALUES
(7788, 'SCOTT', 'ANALYST', 7566,
TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7839, 'KING', 'PRESIDENT', NULL,
TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);
INSERT INTO EMP VALUES
(7844, 'TURNER', 'SALESMAN', 7698,
TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, NULL, 30);
INSERT INTO EMP VALUES
(7876, 'ADAMS', 'CLERK', 7788,
TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);
INSERT INTO EMP VALUES
(7900, 'JAMES', 'CLERK', 7698,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30);
INSERT INTO EMP VALUES
(7902, 'FORD', 'ANALYST', 7566,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7934, 'MILLER', 'CLERK', 7782,
TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);
commit;
step :- 5
declare
cursor c1 is select * from dept;
k number:=0;
m number:=0;
begin
for i in c1 loop
k:=k+1;
--dbms_output.put_line('k:'||k);
--dbms_output.put_line('i.deptno:'||i.deptno);
m:=0;
for j in 1..5 loop
m:=m+1;
--dbms_output.put_line('m:'||m);
--dbms_output.put_line('i.deptno:'||i.deptno);
insert into emp values
(9000+emp_seq.nextval, 'SMITH'||'_'||emp_seq.currval, 'CLERK'||'_'||emp_seq.currval, 7902,
TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, i.deptno);
end loop;
end loop;
commit;
exception
when others then
dbms_output.put_line('Exception occured:'||sqlerrm);
end;
step :-6
create table dept3 as select * from dept where 1=2;
create table emp3 as select * from emp where 1=2;
alter table dept add object_id number;
alter table dept add status varchar(20);
alter table dept add err_msg varchar2(200);
alter table emp add object_id number;
-- I have not included the alter statements in the inital creation because i dont want them to insert into dept3 and emp3
CREATE OR REPLACE
PACKAGE test_b
AS
g_batch_id NUMBER;
PROCEDURE emp_ins(
p_EMPNO NUMBER,
p_ENAME VARCHAR2,
p_JOB VARCHAR2,
p_MGR NUMBER,
p_HIREDATE DATE,
p_SAL NUMBER,
p_COMM NUMBER,
p_DEPTNO NUMBER);
PROCEDURE dept_ins(
p_DEPTNO NUMBER,
p_dname VARCHAR2 ,
p_LOC VARCHAR2,
p_batch NUMBER);
PROCEDURE validate_prc;
PROCEDURE main;
TYPE dept_t
IS
TABLE OF dept%ROWTYPE;
hdr_tbl dept_t;
TYPE emp_t
IS
TABLE OF emp%ROWTYPE;
line_tbl emp_t;
TYPE dept_i_t
IS
TABLE OF dept3%ROWTYPE;
hdr_ins_tbl dept_i_t;
TYPE emp_i_t
IS
TABLE OF emp3%ROWTYPE;
line_ins_tbl emp_i_t;
END;
-- pacakge body
CREATE OR REPLACE
PACKAGE body test_b
AS
PROCEDURE emp_ins(
p_EMPNO NUMBER,
p_ENAME VARCHAR2,
p_JOB VARCHAR2,
p_MGR NUMBER,
p_HIREDATE DATE,
p_SAL NUMBER,
p_COMM NUMBER,
p_DEPTNO NUMBER)
IS
BEGIN
INSERT
INTO EMP3
EMPNO ,
ENAME ,
JOB ,
MGR ,
HIREDATE ,
SAL ,
COMM ,
DEPTNO
VALUES
P_EMPNO ,
P_ENAME ,
P_JOB ,
P_MGR ,
P_HIREDATE ,
P_SAL ,
P_COMM ,
P_DEPTNO
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('EXCEPTION AT EMP INSERT'||SQLERRM);
END;
PROCEDURE dept_ins
p_DEPTNO NUMBER,
p_dname VARCHAR2 ,
p_LOC VARCHAR2,
p_batch NUMBER
IS
BEGIN
INSERT
INTO DEPT3
DEPTNO ,
DNAME ,
LOC ,
batch_id
VALUES
p_DEPTNO ,
p_DNAME ,
p_LOC ,
p_batch
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('EXCEPTION AT DEPT INSERT'||SQLERRM);
END ;
PROCEDURE validate_prc
IS
CURSOR c1
IS
SELECT * FROM dept WHERE status IS NULL ;--AND rownum <25;
CURSOR c2(p_dept NUMBER )
IS
SELECT * FROM emp WHERE deptno=p_dept;
e_validation EXCEPTION;
BEGIN
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO hdr_tbl limit 5000;
SELECT emp_seq.nextval INTO g_batch_id FROM dual;
EXIT
WHEN hdr_tbl.count = 0;
dbms_output.put_line('batch'||g_batch_id);
END LOOP;
CLOSE c1;
dbms_output.put_line('C1 closed');
--------- Loading data into the inv line table type -------------------------------
FOR i IN 1 .. hdr_tbl.count
LOOP
dbms_output.put_line('started validation');
-- do header level validations
IF hdr_tbl(i).dname IS NULL THEN
hdr_tbl(i).status := 'ERROR';
hdr_tbl(i).err_msg :=',DNAME is null';
END IF;
OPEN c2(hdr_tbl(i).deptno);
LOOP
FETCH c2 BULK COLLECT INTO line_tbl;
-- EXIT WHEN c2%NOTFOUND;
END LOOP;
CLOSE c2;
FOR j IN 1 .. line_tbl.count
LOOP
-- do line validations
IF line_tbl(j).ename IS NULL THEN
hdr_tbl(i).status := 'ERROR';
hdr_tbl(i).err_msg :=',ENAME is null';
END IF;
BEGIN
FORALL j IN line_tbl.FIRST .. line_tbl.LAST
SAVE EXCEPTIONS
UPDATE EMP
SET object_id =3
-- I have multiple columns to update based on validations
WHERE deptno =hdr_tbl(i).deptno------------
AND empno =line_tbl (j).empno;
COMMIT;
line_tbl.DELETE;
dbms_output.put_line( 'Successfully updated emp temp table.');
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
dbms_output.put_line( 'Error while updating line temp table. ' || sqlerrm );
FOR j IN 1 .. sql%BULK_EXCEPTIONS.COUNT
LOOP
DBMS_OUTPUT.put_line(' occurred during line temp table updation ' || sql%BULK_EXCEPTIONS(i).ERROR_INDEX );
END LOOP;
raise e_validation;
END;
END LOOP; -- j
--CLOSE c2;
IF hdr_tbl(i).err_msg IS NULL THEN
hdr_tbl (i).status := 'VALID';
hdr_tbl (i).err_msg := NULL;
END IF;
-- even if I have line validation failed I have to update header status and erorr msg
BEGIN
FORALL i IN hdr_tbl.FIRST .. hdr_tbl.LAST
SAVE EXCEPTIONS
UPDATE DEPT
SET object_id =4,
status = hdr_tbl (i).status,
err_msg = hdr_tbl (i).err_msg
-- batch_id =
-- I have multiple columns to update based on validations
WHERE deptno = hdr_tbl (i).deptno
AND status IS NULL; ------------
COMMIT;
hdr_tbl.DELETE;
dbms_output.put_line( 'Successfully updated dept temp table.');
--close c1;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
dbms_output.put_line( 'Error while updating hdr temp table. ' || sqlerrm );
FOR i IN 1 .. sql%BULK_EXCEPTIONS.COUNT
LOOP
DBMS_OUTPUT.put_line(' occurred during line temp table updation ' || sql%BULK_EXCEPTIONS(i).ERROR_INDEX );
END LOOP;
raise e_validation;
END;
END LOOP; --i
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('EXCEPTION AT validate'||SQLERRM);
END ;
PROCEDURE main
IS
CURSOR dept_ins_cur
IS
SELECT * FROM dept WHERE status='VALID';
CURSOR emp_ins_cur(p_deptno NUMBER)
IS
SELECT * FROM emp WHERE deptno= p_deptno;
BEGIN
validate_prc;
OPEN dept_ins_cur;
LOOP
FETCH dept_ins_cur BULK COLLECT INTO hdr_ins_tbl limit 1000
EXIT
WHEN dept_ins_cur%NOTFOUND;
END LOOP;
CLOSE dept_ins_cur;
--------- Loading data into the inv line table type -------------------------------
FOR i IN 1 .. hdr_tbl.count
loop
dept_ins(hdr_ins_tbl(i).deptno ,
hdr_ins_tbl(i).DNAME ,
hdr_ins_tbl(i).LOC , emp_seq.nextval);
commit;
OPEN emp_ins_cur(hdr_ins_tbl(i).deptno);
LOOP
FETCH emp_ins_cur BULK COLLECT INTO line_ins_tbl;
--EXIT WHEN emp_ins_cur%NOTFOUND;
END LOOP;
CLOSE emp_ins_cur;
for j in 1..line_ins_tbl.count loop
emp_ins(line_ins_tbl(j).EMPNO ,
line_ins_tbl(j).ENAME ,
line_ins_tbl(j).JOB ,
line_ins_tbl(j).MGR ,
line_ins_tbl(j).HIREDATE ,
line_ins_tbl(j).SAL ,
line_ins_tbl(j).comm ,
line_ins_tbl(j).DEPTNO );
end loop;
end loop;
commit;
BEGIN
forall i IN hdr_ins_tbl.first .. hdr_ins_tbl.last
SAVE exceptions
UPDATE dept
SET status = 'INSERTED',
err_msg = null
WHERE deptno=hdr_ins_tbl (i).deptno
AND status = 'VALID';
COMMIT;
hdr_ins_tbl.delete;
dbms_output.put_line( 'inserting into temp tables.');
EXCEPTION
WHEN OTHERS THEN
rollback;
end;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('exception in main' ||SQLERRM);
END ;
END;
Thanks in advance...
Message was edited by: 888025Hi, I have problem with the following pl/sql block
Well, as Hoek already said, that is the understatement of the century.
I can't be absolutely certain but I think that set of DDL and code that you posted has just about every possible error and design issue that there is! It would make an excellent addition to BluShadow's FAQs an an example of what NOT to do.
I don't think it is even possible to 'fix the basics first' as Hoek suggested. IMHO the first step needs to be to create a functional requirements document (FRD) that explains in detail WHAT needs to be done. That doc should also contain info about how any errors/recovery/restart is to be handled. It is premature to try to implement ANY solution without first knowing what is needed functionally.
Once the FRD is done you should do a walk-through based on your current architecture and sample data to make sure that the document really covers ALL of the steps that need to be performed and that it adequately explains how to deal with any processing or data issues that might arise.
The next document you need is the TRD - Technical Requirements Doc that covers the different technical implementions of the FRD that can be done and the advantages/disadvantages of each.
Then you can start working on a prototype.
1. The DDL you posted isn't coherent - there are CREATE table statements and then later ALTER statements that add additional columns. There doesn't appear to be any reason for not including ALL of the columns in the CREATE table statement.
2. You are using PL/SQL types instead of SQL types. That makes it impossible to use those types in SQL statements and makes it much more difficult to test since it is much easier to test a query in SQL (e.g. using sql*plus) that to embed the query in PL/SQL.
3. You are defining the same type twice but giving it different names.
TYPE dept_t
IS
TABLE OF dept%ROWTYPE
INDEX BY binary_integer;
TYPE dept_i_t
IS
TABLE OF dept%ROWTYPE
INDEX BY binary_integer;
Those are both based on the same DEPT table! Why the duplication?
Also you are using associative arrays instead of just using nested tables. Get rid of the INDEX BY clause.
4. You have some serious architectural and data model issues
-- Assume the following scenario, we are validating dept (master) and emp(child) which are my temporary tables and updating the status back to
-- dept ( for all the validation errors, even if we have any validation at child it has to update the header record with error message),
Why would you do that? You say 'it has to update the header record ...'. Says who? That is just one indication that you are trying to implement a 'solution' before you have adequately defined the 'problem'.
Typically you would NOT alter any of the data tables; any validation errors/issues would get inserted into a table specifically designed to hold/log those issues. That table would contain key field values to correlate with the source of the error.
Those 'master' and 'child' entities are two SEPARATE things. Issues with a 'master' row have NOTHING to do with any possible child rows.
And issues with a 'child' row have NOTHING to do with any possible master rows. The ONLY connection between 'child' and 'master' is the foreign key that correlates them.
So you don't necessarily have to validate the 'child' rows in sync with their 'master' row. In many cases you would have a procedure that performs validation of the entire set of 'master' rows and log those issues/problems. You would use a different procedure to validate the entire set of 'child' rows and log their issues.
Those validation procedures can often work with ALL of the data using SQL statements instead of bulk processing.
5. You are using loop constructs that are not valid for the type of processing you are using
LOOP
FETCH c1 BULK COLLECT INTO hdr_tbl;
EXIT
WHEN c1%NOTFOUND;
END LOOP;
There can be NO exit since the bulk collect with either get EVERYTHING or NOTHING. Possibly that is just a holdover from your attempt to use the LIMIT clause but you removed that clause from the FETCH; I don't know.
There is so much wrong with what you posted it is really rather pointless to try to 'fix' it.
I suggest you start over and clarify and DOCUMENT the actual requirements without prejudice about the solution that someone seems to want to force on you. -
Can't create a sequence within a pl/sql block with execute immediate.
Hi All. I created a user and granted it the 'create sequence' privilege though a role. In a pl/sql block I try to create a sequence using 'execute immediate' but get a 1031-insufficient privileges error. If I grant create sequence directly to the user, the pl/sql block completes successfully. Can anyone explain this behavior? We're running 11.2 Enterprise Editon.
Thanks,
MarkIn a definer's rights stored procedure (the default), you only have access to privileges that have been granted directly, not via a role.
There are two basic reasons for that. First, roles can be enabled or disabled, default and non-default, password-protected, etc. so the set of roles a particular user actually has is session-specific. Oracle needs to know at compile time what privileges the owner of the procedure has. The only way to do that (without deferring the privilege check) is to ignore privileges granted through roles.
Second, since 99% of privilege management DBAs do involves granting and revoking roles, it's helpful that changing role privileges will never cause objects to be marked invalid and recompiled which can have side-effects on applications. DBAs only need to worry about causing problems on those rare cases where they are granting or revoking direct privileges to users.
You can create an invoker's rights stored procedure by adding the clause (AUTHID CURRENT_USER). That defer's the security check to run-time but allows the procedure to see privileges granted through roles in the current session. But that means that the caller of the procedure would need to have the CREATE SEQUENCE privilege through the role, not the owner of the procedure.
And just to make the point, dynamic object creation in PL/SQL is almost always a red flag that there is something problematic in your design. If you are creating sequences dynamically, that means that you'd have to refer to them dynamically throughout your code which means that your inserts would need to use dynamic SQL. That's not a particularly easy or safe way to develop code.
Justin -
Exception in declarative section to propagating in PL/SQL Block
Hi All, I have a requirement to send emails to some receipient whenever there is an error in a process. The is working untill the put a wrong database link in the parameter, the cursor is in declarative statement, hence when other exception does not work, create and enclosing block around the initial block so that the exception can propagate to the enclosing block, but this does not work either, please advice. Below is the a brief pseudo code. The bold is the initial block. Please advice.
DECLARE
Invalid_table EXCEPTION;
PRAGMA EXCEPTION_INIT(Invalid_table, -00942);
BEGIN
declare
c_test number;
cursor c1 is select 1 from tt@sro4link1 --- wrong databaselink sent as a parameter
where 1 =1;
*/*Because the error is in the cursor select, no email is been sent, that was the reason I put an enclosing block, but the exception is not propagate either */*
BEGIN
OPEN C1;
FETCH C1 into c_test;
CLOSE C1;
EXCEPTION
WHEN OTHERS THEN
--- Send email
END; EXCEPTION
WHEN Invalid_table THEN
--- send email
END;
/Ade2 wrote:
it is not a dynamic sql. Your description is not very clear about what is code and what is pseudo code, but if you are using substitution variables in sqlplus, then that is dynamic SQL.
sqlplus scans for substitution variables, prompts when needed, replaces the variable (substitutes) with the text input and passes the entire result to the database for validation.
If the substitution text input results in an invalid PL/SQL block then a compilation error is returned from the database. The PL/SQL cannot be compiled, it never runs, no run time exceptions are possible.
So you cannot use exceptions to detect errors in values input to substitution variables.
SQL> declare
2 l_dummy number;
3 begin
4 select 1 into l_dummy from dual;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL> declare
2 l_dummy number;
3 begin
4 &5
5 end;
6 /
Enter value for 5: select 1 into l_dummy from dual;
old 4: &5
new 4: select 1 into l_dummy from dual;
PL/SQL procedure successfully completed.
SQL> /
Enter value for 5: this will not compile
old 4: &5
new 4: this will not compile
this will not compile
ERROR at line 4:
ORA-06550: line 4, column 8:
PLS-00103: Encountered the symbol "WILL" when expecting one of the following:
:= . ( @ % ; -
Db_link name and synonym in PL/SQL block
Hi,
I'm having a problem with synonyms in PL/SQL block.
Say, I have two schemas A and B.
In schema A, I create some tables and stored procedures.
In schema B, I create a db link connecting to schema A. Then I create some synonyms for tables and stored procedures in schema A with the db link. In stored procedures created in schema B, I need to access or reference objects in schema by using synonyms.
My problem is, if schema A and schema B reside on the same db instance and the instance's global_names is set to true, I will not be able to reference any synonyms in stored procedures created in schema B. The error message is,
PL/SQL: ORA-00980: synonym translation is no longer valid.
A simple example:
In schema A,
create table mytable (A char(2));
In schema B,
create database link <global_name-for-schema-A>@loopback connect to A identified by <A-pwd> using '<net-service-name-for-schema-A>';
create synonym mytable for mytable@<global_name-for-schema-A>@loopback;
declare
a char;
begin
select * from mytable;
end;
But I have no problem to access the synonym-ed objects in SQL*PLUS.
Please help.
ThanksI had the similar problem i did a work around like below
SQL>select max(col1) from tab1;
MAX(COL1)
21161910
SQL>get a
1 declare
2 a number;
3 begin
4 select max(col1) into a from tab1;
5 dbms_output.put_line(a);
6* end;
SQL>@a
select max(col1) into a from tab1;
ERROR at line 4:
ORA-06550: line 4, column 1:
PL/SQL: ORA-00980: synonym translation is no longer valid
ORA-06550: line 4, column 1:
PL/SQL: SQL Statement ignored
Created a view on top of the synonym
SQL>create or replace view tab1_v as select * from tab1@db1;
View created.
changed the pl/sql block as below to get it from view instead of synonymn
declare
a number;
begin
select max(col1) into a from tab1;
dbms_output.put_line(a);
end;
Now it worked
SQL>@a
21161910
PL/SQL procedure successfully completed.
Maybe you are looking for
-
Hi all Getting a new error in the PDA Error: Synchronization started Connection set up (without proxy) to: http://<server>:50000/meSync/servlet/meSync?~sysid=mi1& Connection to server failed. Error: cannot connect (java.io.FileNotFoundEx
-
When I double-click on the Adobe Photoshop Elements 8 desktop icon, an error messsage appears. The title line says: OWL ORPHANAGE: PhotoshopElementsEditor.exe - System Error Then the message ; The program can't start because CoreFoundation.dll is mis
-
Hi All, The valuation reports which are required in case of forward contracts....is that same as 'key date valuation'. If no, kindly let me know which report to be used. Also, in both cases, what is the accounting entries? regards Sur
-
Material master codification & inventory mgmt- construction industry
Hi, I am designing the process for a client in the construction industry. The implementation will include integration with PS module. The client is working on different projects and the materials requirement for each project differ from the other. Ex
-
I am trying to upload about 25 songs onto my iPod. There is a white circle next to every single song I am trying to upload. I have deleted songs off of my iPod to make enough room, it says I have 3.67 GB free. I also have the manually manage music an