AUTONOMOUS_TRANSACTION
Hello all
I want to use AUTONOMOUS_TRANSACTION in my proceadure but it did not copiled
error: PRAGMA AUTONOMOUS_TRANSACTION is not a supported PRAGMA
i am using forms6i.
any suggestion
thanks
it means i have to create a database proceadure ? can't i use it on form's programe unit? i was thinking that can be used in pl/sql .
i don't want to involve database procedures then what will be the alternative of
AUTONOMOUS_TRANSACTION at form because i have to use commit at several places without commiting the data placed on blocks of form eg:
PROCEDURE abc IS
PRAGMA AUTONOMOUS_TRANSACTION;
var_1 number;
BEGIN
update naj set strg='TEST';
commit;
END;
i want to commit only this update not the data on form. any suggestion ?
thanks
Najeeb
Similar Messages
-
Autonomous_transaction in oracle 11g
Hi
I am stuck with the concept of autonomous_transaction in oracle 11g. The situation is like that:
I have a table TABLE_A and i want to delete a row within it.
TABLE_A has a after delete trigger T_D_TABLE_A with autonomous_transaction property and it tries to delete a row in table TABLE_B.
TABLE_B has also a before delete trigger T_D_TABLE_B with autonomous_transaction and it raises application error when the reletad row is tried to be deleted.
So i want to delete a row in TABLE_A and and even if an application error is raised in the trigger T_D_TABLE_B, I want the row that i tried to delete in TABLE_A to be deleted.
Since I am using the autonomous_transaction property of 11g, I think the above code should behave like at my will but when i run it i encountered an application error that saying the row in TABLE_B can not be deleted and whole process even the deletion of the row in TABLE_A is rolled back. I think this is against the logic of autonomous_transaction property of Oracle 11g.
Can you help me with this problem?
Thanks in advance.
PS: if you request more detailed explanation about the problem, ı can provide the case environment and the code.CREATE TABLE GOKHAN_DENEME (EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10),
EJOB VARCHAR2(9),
DEPTNO NUMBER(2));
INSERT INTO GOKHAN_DENEME VALUES (7369, 'SMITH', 'CLERK', 20);
INSERT INTO GOKHAN_DENEME VALUES (7499, 'ALLEN', 'SALESMAN', 30);
INSERT INTO GOKHAN_DENEME VALUES (7521, 'WARD', 'SALESMAN', 30);
INSERT INTO GOKHAN_DENEME VALUES (7566, 'JONES', 'MANAGER', 20);
CREATE TABLE GOKHAN_DENEME_2 (MGR NUMBER(4) NOT NULL,
COMM NUMBER(7, 2));
INSERT INTO GOKHAN_DENEME_2 VALUES (7369, 20);
INSERT INTO GOKHAN_DENEME_2 VALUES (7499, 30);
INSERT INTO GOKHAN_DENEME_2 VALUES (7521, 30);
INSERT INTO GOKHAN_DENEME_2 VALUES (7566, 20);
create or replace
TRIGGER GOKHAN_DENEME_TRG1
AFTER DELETE ON GOKHAN_DENEME FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
RAISE_APPLICATION_ERROR(-20000, 'ERRORRRRRR');
END;
create or replace
TRIGGER GOKHAN_DENEME_2_TRG1
AFTER DELETE ON GOKHAN_DENEME_2 FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
DELETE FROM GOKHAN_DENEME WHERE EMPNO = :OLD.MGR;
COMMIT;
END;
the delete statement is:
DELETE FROM GOKHAN_DENEME_2 WHERE MGR = 7566;
the error mesage is:
Error starting at line 74 in command:
DELETE FROM GOKHAN_DENEME_2 WHERE MGR = 7566
Error report:
SQL Error: ORA-20000: ERRORRRRRR
ORA-06512: at "DBO.GOKHAN_DENEME_TRG1", line 49
ORA-04088: error during execution of trigger 'DBO.GOKHAN_DENEME_TRG1'
ORA-06512: at "DBO.GOKHAN_DENEME_2_TRG1", line 10
ORA-04088: error during execution of trigger 'DBO.GOKHAN_DENEME_2_TRG1'
20000. 00000 - "%s"
*Cause: The stored procedure 'raise_application_error'
was called which causes this error to be generated.
*Action: Correct the problem as described in the error message or contact
the application administrator or DBA for more information. -
Parallel pipelined table function, autonomous_transaction to global tmp tab
Hi,
i try to speed up my parallel pipelined table function and switch from pl/sql collection to global temporary table inside.
This requires to use PRAGMA AUTONOMOUS_TRANSACTION (and commit), because inserting into global temporary table (DML)
within select - for invoking the table function - is not allowed without.
As a consequence of commit it next requires to have on commit preserve rows for the global temporary table.
Now:
Inserts into the global temporary table are done - indicated by sql%rowcount.
But a select afterwards doesn't show any record anymore.
Here is a program to demonstrate it:
set serveroutput on;
drop type TestTableOfNumber_t;
create or replace type TestTableOfNumber_t is table of number;
drop type TestStatusList;
drop type TestStatusObj;
create or replace type TestStatusObj as object(
sid number,
ctr1 number,
ctr2 number,
ctr3 number
create or replace type TestStatusList is table of TestStatusObj;
drop table TestTmpTable;
create global temporary table TestTmpTable (
value number
) on commit preserve rows;
create or replace package test_pkg
as
type TestStatusRec is record (
sid number,
ctr1 number,
ctr2 number,
ctr3 number
type TestStatusTab is table of TestStatusRec;
function FillTmpTable(id in varchar2)
return TestStatusRec;
FUNCTION ptf (p_cursor IN sys_refcursor)
RETURN TestStatusList PIPELINED
PARALLEL_ENABLE(PARTITION p_cursor BY any);
end;
create or replace package body test_pkg
as
function FillTmpTable(id in varchar2)
return TestStatusRec
is
PRAGMA AUTONOMOUS_TRANSACTION;
result TestStatusRec;
sid number;
type ton is table of number;
tids TestTableOfNumber_t := TestTableOfNumber_t();
records number := 0;
begin
select userenv('SID') into sid from dual;
result.sid := sid;
delete from TestTmpTable;
for i in 1..100 loop
tids.extend;
tids(tids.last) := i;
end loop;
forall i in 1..tids.count
insert into TestTmpTable (value) values (tids(i));
-- get number of records inserted
records := sql%rowcount;
result.ctr1 := records;
-- retrieve again before commit
select count(*) into records from TestTmpTable;
result.ctr2 := records;
commit;
-- retrieve again after commit
select count(*) into records from TestTmpTable;
result.ctr3 := records;
return result;
end;
FUNCTION ptf (p_cursor IN sys_refcursor)
RETURN TestStatusList PIPELINED
PARALLEL_ENABLE(PARTITION p_cursor BY any)
IS
rec test_pkg.TestStatusRec;
value number;
sid number;
ctr integer := 0;
BEGIN
select userenv('SID') into sid from dual;
rec := FillTmpTable('IN PTF');
LOOP
FETCH p_cursor into value;
EXIT WHEN p_cursor%NOTFOUND;
ctr := ctr + 1;
END LOOP;
-- as a result i am only interested in the results of FillTmpTable():
PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
RETURN;
END;
end;
declare
tons TestTableOfNumber_t;
counts TestTableOfNumber_t;
status test_pkg.TestStatusRec;
statusList test_pkg.TestStatusTab;
begin
status := test_pkg.FillTmpTable('MAIN');
dbms_output.put_line('main thread:'
|| ' sid #' || status.sid
|| ' / #' || status.ctr1 || ' inserted '
|| ' / #' || status.ctr2 || ' before commit'
|| ' / #' || status.ctr3 || ' after commit');
select value bulk collect into tons from TestTmpTable;
select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2) */ value from TestTmpTable tab)));
for i in 1..StatusList.count loop
dbms_output.put_line('worker thread #' || i || ':'
|| ' sid #' || statusList(i).sid
|| ' / #' || statusList(i).ctr1 || ' inserted '
|| ' / #' || statusList(i).ctr2 || ' before commit'
|| ' / #' || statusList(i).ctr3 || ' after commit');
end loop;
end;
/The output is:
main thread: sid #881 / #100 inserted / #100 before commit / #100 after commit
worker thread #1: sid #421 / #100 inserted / #0 before commit / #0 after commit
worker thread #2: sid #321 / #100 inserted / #0 before commit / #0 after commitThe 1st line is for the main thread invoking FillTmpTable().
The next #2 lines are for the worker threads of the parallel pipelined table function for invoking the same FillTmpTable().
For the main thread everything is as expected.
But for the worker threads the logs for before commit and after commit both give #0 for the number of available records in the global temporary table.
However all indicate #100 for the SQL insert
regards,
Frank
Edited by: user8704911 on Jul 7, 2011 10:13 AM
Edited by: user8704911 on Jul 7, 2011 10:20 AM
Edited by: user8704911 on Jul 7, 2011 10:27 AMSQL> select * from v$version;
BANNER
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
CORE 11.1.0.7.0 Production
TNS for Linux: Version 11.1.0.7.0 - Production
NLSRTL Version 11.1.0.7.0 - Production
SQL> set serveroutput on;
SQL> drop type TestTableOfNumber;
drop type TestTableOfNumber
ERROR at line 1:
ORA-04043: object TESTTABLEOFNUMBER does not exist
SQL> /
drop type TestTableOfNumber
ERROR at line 1:
ORA-04043: object TESTTABLEOFNUMBER does not exist
SQL>
SQL> create or replace type TestTableOfNumber_t is table of number;
2 /
Type created.
SQL>
SQL> drop type TestStatusObj;
drop type TestStatusObj
ERROR at line 1:
ORA-04043: object TESTSTATUSOBJ does not exist
SQL> /
drop type TestStatusObj
ERROR at line 1:
ORA-04043: object TESTSTATUSOBJ does not exist
SQL>
SQL> create or replace type TestStatusObj as object(
2 sid number,
3 ctr1 number,
4 ctr2 number,
5 ctr3 number
6 );
7 /
Type created.
SQL>
SQL> drop type TestStatusList;
drop type TestStatusList
ERROR at line 1:
ORA-04043: object TESTSTATUSLIST does not exist
SQL> /
drop type TestStatusList
ERROR at line 1:
ORA-04043: object TESTSTATUSLIST does not exist
SQL>
SQL> create or replace type TestStatusList is table of TestStatusObj;
2 /
Type created.
SQL>
SQL> drop table TestTmpTable;
drop table TestTmpTable
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> /
drop table TestTmpTable
ERROR at line 1:
ORA-00942: table or view does not exist
SQL>
SQL> create global temporary table TestTmpTable (
2 value number
3 ) on commit preserve rows;
Table created.
SQL> /
create global temporary table TestTmpTable (
ERROR at line 1:
ORA-00955: name is already used by an existing object
SQL>
SQL> create or replace package test_pkg
2 as
3
4 type TestStatusRec is record (
5 sid number,
6 ctr1 number,
7 ctr2 number,
8 ctr3 number
9 );
10
11 type TestStatusTab is table of TestStatusRec;
12
13 function FillTmpTable(id in varchar2)
14 return TestStatusRec;
15
16 FUNCTION ptf (p_cursor IN sys_refcursor)
17 RETURN TestStatusList PIPELINED
18 PARALLEL_ENABLE(PARTITION p_cursor BY any);
19
20 end;
21 /
Package created.
SQL>
SQL> create or replace package body test_pkg
2 as
3
4 function FillTmpTable(id in varchar2)
5 return TestStatusRec
6 is
7 PRAGMA AUTONOMOUS_TRANSACTION;
8
9 result TestStatusRec;
10
11 sid number;
12
13 type ton is table of number;
14 tids TestTableOfNumber_t := TestTableOfNumber_t();
15
16 records number := 0;
17 begin
18 select userenv('SID') into sid from dual;
19 result.sid := sid;
20
21 delete from TestTmpTable;
22
23 for i in 1..100 loop
24 tids.extend;
25 tids(tids.last) := i;
26 end loop;
27
28 forall i in 1..tids.count
29 insert into TestTmpTable (value) values (tids(i));
30
31 -- get number of records inserted
32 records := sql%rowcount;
33 result.ctr1 := records;
34
35 -- retrieve again before commit
36 select count(*) into records from TestTmpTable;
37 result.ctr2 := records;
38
39 commit;
40
41 -- retrieve again after commit
42 select count(*) into records from TestTmpTable;
43 result.ctr3 := records;
44
45 return result;
46 end;
47
48 FUNCTION ptf (p_cursor IN sys_refcursor)
49 RETURN TestStatusList PIPELINED
50 PARALLEL_ENABLE(PARTITION p_cursor BY any)
51 IS
52 rec test_pkg.TestStatusRec;
53 value number;
54 sid number;
55 ctr integer := 0;
56 BEGIN
57 select userenv('SID') into sid from dual;
58 rec := FillTmpTable('IN PTF');
59 LOOP
60 FETCH p_cursor into value;
61 EXIT WHEN p_cursor%NOTFOUND;
62 ctr := ctr + 1;
63 END LOOP;
64
65 -- as a result i am only interested in the results of FillTmpTable():
66 PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
67
68 RETURN;
69 END;
70 end;
71 /
Package body created.
SQL>
SQL> declare
2 tons TestTableOfNumber_t;
3 counts TestTableOfNumber_t;
4 status test_pkg.TestStatusRec;
5 statusList test_pkg.TestStatusTab;
6 begin
7 status := test_pkg.FillTmpTable('MAIN');
8 dbms_output.put_line('main thread:'
9 || ' sid #' || status.sid
10 || ' / #' || status.ctr1 || ' inserted '
11 || ' / #' || status.ctr2 || ' before commit'
12 || ' / #' || status.ctr3 || ' after commit');
13
14 select value bulk collect into tons from TestTmpTable;
15
16 select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2
) */ value from TestTmpTable tab)));
17
18 for i in 1..StatusList.count loop
19 dbms_output.put_line('worker thread #' || i || ':'
20 || ' sid #' || statusList(i).sid
21 || ' / #' || statusList(i).ctr1 || ' inserted '
22 || ' / #' || statusList(i).ctr2 || ' before commit'
23 || ' / #' || statusList(i).ctr3 || ' after commit');
24 end loop;
25
26 end;
27 /
main thread: sid #1023 / #100 inserted / #100 before commit / #100 after commit
worker thread #1: sid #1045 / #100 inserted / #100 before commit / #100 after
commit
worker thread #2: sid #1019 / #100 inserted / #100 before commit / #100 after
commit
PL/SQL procedure successfully completed.
SQL> I am getting a different result.
Regards
Raj -
Where i use pragma autonomous_transaction in trigger?
where i use pragma autonomous_transaction in trigger?
give one example..plsyou've already asked this question:
what is a pragma autonomous_transaction?
judging by your other questions, you need to sit down with a book on oracle fundamentals or go through the documentation website linked in that post or perhaps search on a term here:
http://www.oracle.com/pls/db102/homepage
there are lots of examples in the existing oracle documentation -
About autonomous_transaction
Hi,
The trigger stock_trigger works normally.But after I add these sentences :"PRAGMA AUTONOMOUS_TRANSACTION" and "COMMIT",it doesn't work anymore.And there is no error showed by system.
Anybody cound tell me how to amend this triigger?
many thanks
xiao li
CREATE OR REPLACE TRIGGER stock_trigger
AFTER INSERT ON OOS_list
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION ;
v_no NUMBER(3);
v_money NUMBER(10,2);
k NUMBER(3) DEFAULT 1;
CURSOR g_cursor IS
SELECT A.id C, A.name D, A.unit E, A.i_price F,B.amount G, A.i_price*B.amount H, A.manufacturer I
FROM merchandise_info A, OOS_list B
WHERE A.id = B.id;
BEGIN
SELECT COUNT(*) INTO v_no FROM OOS_list;
IF v_no=30 THEN
SELECT SUM( A.i_price * B.amount ) INTO v_money
FROM merchandise_info A, OOS_list B
WHERE A.id = B.id ;
INSERT INTO stock_list(sid,sdate,smoney) VALUES(cid_seq.nextval,SYSDATE,v_money);
FOR g_record IN g_cursor LOOP
UPDATE a_stock_list
SET id=g_record.C, name=g_record.D, unit=g_record.E, i_price=g_record.F,
mount=g_record.G, a_money=g_record.H, manufacturer=g_record.I
WHERE aid = k;
k := k+1;
END LOOP;
DELETE FROM OOS_list;
dbms_output.put_line('A new list was produced !');
END IF;
COMMIT;
END stock_trigger;I suppose OP means the following difference in the case of autonomous and
ordinar triggers:
SQL> desc t
Name Null? Type
X NUMBER(38)
SQL> select * from t;
no rows selected
SQL> create or replace trigger tr_t after insert on t
2 begin
3 delete from t;
4 end;
5 /
Trigger created.
SQL> insert into t values(1);
1 row created.
SQL> select * from t;
no rows selected
SQL> create or replace trigger tr_t after insert on t
2 declare
3 pragma autonomous_transaction;
4 begin
5 delete from t;
6 commit;
7 end;
8 /
Trigger created.
SQL> insert into t values(1);
1 row created.
SQL> select * from t;
X
1As BluShadow remarked above the autonomous transaction doesn't see any changes have been made by parent transaction, so autonomous trigger can't "clear" the table like the ordinar one. And as Justin pointed out what is the need to commit the
transaction in the trigger ?
Rgds. -
What would happen if function is declared as autonomous_transaction
Hi all,
Can any one tell me what would happen if function is declared as autonomous_transaction ?
Will it affect other DML's in the current session .Please help me.
Thanks in advance
Regards,
P PrakashIn (another) addition, I recall getting deadlock errors as well, due to a totally wrongly defined transaction, using slow-by-slow processing (many moons ago, but I still wake up screaming in the middle of the night when dreaming of that code).
Will it affect other DML's in the current session .Please help me.It depends on in what way you're applying autonomous transactions. From that point of view you gave us little information sofar.
It depends on the understanding you have of them, regarding how they work, and what surprises/data corruption/errors they can give you.
We don't know what you're trying to implement here, but I'd stay far from using an autonomous transaction.
They're only good for logging errors.
Not for fixing datamodel issues or fixing poorly designed transactions based on incomplete/incorrect business rules.
They are not workarounds.
That's been my rule as well for years now.
In general you need to stay away from them. Far far away. Just like the WHEN OTHERS exception.
And especially when you've come to believe that an autonomous transaction will save your day, while it's doing something else than errorlogging in a separate procedure call which in it's turn an autonomous transaction!
Suggest you read up on DML Error Logging then.
You can search http://asktom.oracle.com for more examples and explanations.
Also Metalink/My Oracle Support, if you have access. -
Pragma autonomous_transaction
Hi,
I can commit inside a proc/func. If i'm giving "autonomous_transaction" pragma to any proc/func definition, then what type of advantages i'm going to earn?Pragma autonomous_transaction is used to a kind of intermediate commit or rather for a peice of code in a session without committing the other previous transactions.
e.g. If you have few DML's and you want to log the error in case any DML fails in an error log tbale and commit the data into error log table but you dont want the DML which failed in between to be committed.
In such case you use Pragma autonomous_transaction.
You write the insert statement and Pragma autonomous_transaction for error log table into a separate procedure call that procedure if the DML fails.
The commit inside the called procedure commits the record inserted into error log table but DML before it remains unaffected.
Regrads
Arun -
Need help in AUTONOMOUS_TRANSACTION(pl/sql)
Hi,
I'm havaing a procedure which is calling a autonomous transaction.
I'm unable to get the changes made by the caller procedure. The commit and rollback of the session is controled by the JSP code and not in procedure.
I have gone thro doc and came to know unless commit is made in the caller procedure autonomous transaction can't get the reflected changes.
Any other way ?
Scenario
JSP -> call C1
on sucess -> commit
else -> rollback
Caller Procedure(C1) Autonomous Procedure(A1)
Insert .... Select form insert and update
Update .... of C1 (Not known:no_data_found/
call A1 old_data)
Insert ...
END Commit
END;
Regards,
Donald.Hi,
I'm havaing a procedure which is calling a autonomous transaction.
I'm unable to get the changes made by the caller procedure. The commit and rollback of the session is controled by the JSP code and not in procedure.
I have gone thro doc and came to know unless commit is made in the caller procedure autonomous transaction can't get the reflected changes.
Any other way ?
Scenario
JSP -> call C1
on sucess -> commit
else -> rollback
Caller Procedure(C1) Autonomous Procedure(A1)
Insert .... Select form insert and update
Update .... of C1 (Not known:no_data_found/
call A1 old_data)
Insert ...
END Commit
END;
Regards,
Donald. -
How to delete the data in a table using function
hi all,
i need to delete the data in a table using four parameters in a function,
the parameters are passed through shell script.
How to write the function
Thanks>
But the only thing is that such function cannot be used in SQL.
>
Perhaps you weren't including the use of autonomous transactions?
CREATE OR REPLACE FUNCTION remove_emp (employee_id NUMBER) RETURN NUMBER AS
PRAGMA AUTONOMOUS_TRANSACTION;
tot_emps NUMBER;
BEGIN
SELECT COUNT(*) INTO TOT_EMPS FROM EMP3;
DELETE FROM emp3
WHERE empno = employee_id;
COMMIT;
tot_emps := tot_emps - 1;
RETURN TOT_EMPS;
END;
SQL> SELECT REMOVE_EMP(7499) FROM DUAL;
REMOVE_EMP(7499)
12
SQL> SELECT REMOVE_EMP(7521) FROM DUAL;
REMOVE_EMP(7521)
11
SQL> SELECT REMOVE_EMP(7566) FROM DUAL;
REMOVE_EMP(7566)
10
SQL> -
Message filtering in propagation process (stream replication environment)
Hi!
We have fine configured stream replication in star topology:
ORCL2 <=> ORCL1 <=> ORCL3
Where the ORCL1 is "headquarters" and there is no message flow between ORCL2 and ORCL3.
For some reason we want to filter messages in propagation processes, e.g. DML captured on ORCL1 should be replicated only to ORCL2 or only to ORCL3. There is one propagation process for each "satellite" database.
To solve this problem I have written function:
FUNCTION Replicate_Lcr (
p_lcr IN SYS.lcr$_row_record)
RETURN VARCHAR2 IS
which will be making a decision whether to pass the message (return 'Y') or not (return 'N').
But there is problem: rule is evaluated and function is executed (there is insert into 'stream_log_lcr' table) but value of the expression seems to be 'FALSE' and message (LCR) is not beeing sent to ORCL2 (or to ORCL3).
When I remove function 'Replicate_Lcr' from propagation rule condition then every message captured by capture process on ORCL1 reaches destination database (ORCL2 or ORCL3).
The second observation is that, if I run the same code on ORCL2 or ORCL3 then everything seems to be OK: there is insert into 'stream_log_lcr' table and DML captured on ORCL2 (or ORCL3) appears in ORCL1 ("headquarters").
I suppose that this could be problem with other version of database on "headquarters" (ORCL1) or configuration issues.
I will appreciate every suggestion.
Databases:
ORCL1: 64-bit Windows, ver. 10.2.0.4.0, Windows 2008 server
ORCL2: 32-bit Windows, ver. 10.2.0.1.0, Windows XP
ORCL3: 32-bit Windows, ver. 10.2.0.1.0, Windows XP
SQL code run on ORCL1:
CREATE TABLE stream_log_lcr (
data DATE NOT NULL,
msg SYS.lcr$_row_record NOT NULL
-- simplified, always return 'Y'
CREATE OR REPLACE FUNCTION Replicate_Lcr (
p_lcr IN SYS.lcr$_row_record)
RETURN VARCHAR2 IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
IF p_lcr IS NOT NULL
THEN
INSERT INTO stream_log_lcr
VALUES (SYSDATE,
p_lcr);
COMMIT;
END IF;
RETURN 'Y';
END;
-- create propagation process with above function in rule condition
BEGIN
DBMS_STREAMS_ADM.add_schema_propagation_rules
(schema_name => 'data_schema',
streams_name => 'primary_to_secondary2',
source_queue_name => 'strmadmin.capture_primary',
destination_queue_name => 'strmadmin.from_primary@ORCL2',
include_dml => TRUE,
include_ddl => TRUE,
source_database => 'ORCL1',
and_condition => ' strmadmin.Replicate_Lcr(:dml) = ''Y'' ',
inclusion_rule => TRUE,
queue_to_queue => TRUE);
END;
-- check if function 'Replicate_Lcr' was evoked:
SELECT * FROM stream_log_lcr ORDER BY data;hi porzer,
In Propagation process ( source) also 0 errors. But in apply ( dest ) under statistics under server status is displaying as IDLE. And Coordinator status is APPLYING. In Capture (source) no error. In Applying ( dest ) no error. what else i can do please?
up to now what i did i am telling:
I had 2 databases had one table same table. one database i changed the mode to ARCHIVELOG mode. Another database is in NOARCHIVELOG mode only. In first database setup streams i run. And i run manually 2 .sql files and one .dat file like this :
SQL>@e:\oracle\product\10.2.0\client_2\sysman\report\OTEST_ADMIN_NON_OMS_SETUP.sql
SQL>host e:\oracle\product\10.2.0\client_2\sysman\report\OTEST_ADMIN_NON_OMS_exportimport.bat
SQL>@e:\oracle\product\10.2.0\client_2\sysman\report\OTEST_ADMIN_NON_OMS_startup.sql
Any thing else i can do? i didn't have metalink registration.i hope i am not boring you.
Thanks in advance. -
If we use DML statement in function then that function can be used inside s
if we use DML statement in function then that function can be used inside select query or any DML query?
select f from t2;I think you meant to query t1.
It works if the function is an autonomous transaction:
create or replace function f return number
is
PRAGMA AUTONOMOUS_TRANSACTION;
begin
update t1 set c=2;
commit;
return 1;
end;
select f from t1But as Billy said why would you want to do DML this way. And this is not the way autonomous procedures should be used either.
An an answer to an interview question though nothing wrong with it. -
PL/SQL Mail Utility :: Binary/Ascii/Cc/Bcc/FileDump
I was working on my mail package and decided it was overtly complicated and
stripped it down to its bare bones. Here is what I came up with. Built on a previous
foundation of anothers work, I expanded the functionality considerably. You will find all
the features I think that you will need regarding a mail routine. There is also a nice
filedump routine included which makes very easy to create flat file dumps that you can
then attach to your emails. There are a few pre-reqs in using this though :
- 9iR2+
- DBA_Directories defined as opposed to utl_file paths
- Java Virtual Machine. Document can be found in Note :105472.1 Setup, Configuration,
and Use of the Java Virtual Machine on metalink.
As always, I welcome feedback and suggestions for improvement.
Barry C
http://www.myoracleportal.com
CREATE OR REPLACE PACKAGE mail_tools
AS
-- SENDMAIL supports variable message length with/without attachments
-- QUERY_SERVER allows you to check the status of a mail server to see if it is running
-- DUMP_FLATFILE allows you to dump flat file data from query submitted
-- Query Server to verify that the server is up and running.
-- Connects, Noop Command is executed, Disconnect.
-- GET_MAIL_ADDRESS is utilized in the SENDMAIL procedure
-- Table 100-3 SMTP Reply Codes
-- Reply Code
-- Meaning
-- 211 System status, or system help reply
-- 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user]
-- 220 <domain> Service ready
-- 221 <domain> Service closing transmission channel
-- 250 Requested mail action okay, completed
-- 251 User not local; will forward to <forward-path>
-- 252 OK, pending messages for node <node> started. Cannot VRFY user (e.g., info is not local), but will take message for this user and attempt delivery.
-- 253 OK, <messages> pending messages for node <node> started
-- 354 Start mail input; end with <CRLF>.<CRLF>
-- 355 Octet-offset is the transaction offset
-- 421 <domain> Service not available, closing transmission channel (This may be a reply to any command if the service knows it must shut down.)
-- 450 Requested mail action not taken: mailbox unavailable [for example, mailbox busy]
-- 451 Requested action aborted: local error in processing
-- 452 Requested action not taken: insufficient system storage
-- 453 You have no mail.
-- 454 TLS not available due to temporary reason. Encryption required for requested authentication mechanism.
-- 458 Unable to queue messages for node <node>
-- 459 Node <node> not allowed: reason
-- 500 Syntax error, command unrecognized (This may include errors such as command line too long.)
-- 501 Syntax error in parameters or arguments
-- 502 Command not implemented
-- 503 Bad sequence of commands
-- 504 Command parameter not implemented
-- 521 <Machine> does not accept mail.
-- 530 Must issue a STARTTLS command first. Encryption required for requested authentication mechanism.
-- 534 Authentication mechanism is too weak.
-- 538 Encryption required for requested authentication mechanism.
-- 550 Requested action not taken: mailbox unavailable [for , mailbox not found, no access]
-- 551 User not local; please try <forward-path>
-- 552 Requested mail action aborted: exceeded storage allocation
-- 553 Requested action not taken: mailbox name not allowed [for example, mailbox syntax incorrect]
-- 554 Transaction failed
This version allows for a customized seperator value. Using this function will allow you to
perform fixed width flat files by defining '' for no seperator and then RPAD/LPAD your columns as necessary.
Or use whatever seperator you wish to use, pipe, space, zeros, etc.
-- Example : This will generate a flat file which tabbed seperated
-- DECLARE
-- l_rows NUMBER;
-- l_sql VARCHAR2(32000);
-- BEGIN
-- l_sql := '
-- SELECT rpad(hou.NAME,70) udn_desc
-- , rpad(pcak.segment1,6) coid
-- , rpad(pcak.segment2,4) udn
-- FROM hr_all_organization_units hou, hr.pay_cost_allocation_keyflex pcak
-- WHERE TRUNC (SYSDATE) BETWEEN hou.date_from
-- AND NVL (hou.date_to, ''31-DEC-4712'')
-- AND pcak.cost_allocation_keyflex_id = hou.cost_allocation_keyflex_id
-- GROUP BY pcak.segment1, pcak.segment2, hou.NAME
-- ORDER BY 1, 2, 3
-- l_rows :=
-- dump_flatfile
-- (p_query =>
-- , p_dir => 'INTF000_TABLES'
-- , p_filename => 'test.csv'
-- , p_separator => ' ' -- <= tabbed 5 spaces between each column
-- , p_max_linesize => 32000
-- , p_mode => 'w' -- (w)rite mode or (a)ppend mode
-- END;
FUNCTION dump_flatfile (
p_query IN VARCHAR2
, p_dir IN VARCHAR2
, p_filename IN VARCHAR2
, p_separator IN VARCHAR2
, p_headers IN BOOLEAN DEFAULT FALSE
, p_trailing_separator IN BOOLEAN DEFAULT FALSE
, p_max_linesize IN NUMBER DEFAULT 32000
, p_mode IN VARCHAR2 DEFAULT 'w' )
RETURN NUMBER;
FUNCTION get_mail_address (
addr_list IN OUT VARCHAR2 )
RETURN VARCHAR2;
FUNCTION smtp_command (
command IN VARCHAR2
, ok IN VARCHAR2 DEFAULT '250'
, code OUT VARCHAR2
, DEBUG NUMBER DEFAULT 0 )
RETURN BOOLEAN;
FUNCTION query_server (
smtp_server VARCHAR2
, smtp_server_port PLS_INTEGER DEFAULT 25
, DEBUG NUMBER DEFAULT 0 )
RETURN BOOLEAN;
This procedure uses the UTL_TCP package to send an email message.
Up to three file names may be specified as attachments.
Written: Dave Wotton, 14/6/01 (Cambridge UK)
This script comes with no warranty or support. You are free to
modify it as you wish, but please retain an acknowledgement of
my original authorship.
Amended: Dave Wotton, 10/7/01
Now uses the utl_smtp.write_data() method to send the message,
eliminating the 32Kb message size constraint imposed by the
utl_smtp.data() procedure.
Amended: Dave Wotton, 20/7/01
Increased the v_line variable, which holds the file attachment
lines from 400 to 1000 bytes. This is the maximum supported
by RFC2821, The Simple Mail Transfer Protocol specification.
Amended: Dave Wotton, 24/7/01
Now inserts a blank line before each MIME boundary line. Some
mail-clients require this.
Amended: Dave Wotton, 4/10/01
Introduced a 'debug' parameter. Defaults to 0. If set to
non-zero then errors in opening files for attaching are
reported using dbms_output.put_line.
Include code to hand MS Windows style pathnames.
Amended: Barry Chase, 4/29/03
Added Priority to procedure and also X-Mailer ID.
Removed restrictions for email size limitation as well.
Emails are now formatted text messages, meaning you can
write your message in html format.
And finally, changed from using UTL_SMTP to UTL_TCP instead.
Amended: Barry Chase 11/10/2003
Added session timeout of 4 minutes to prevent hanging server connections
Amended: Barry Chase 12/04/2003
Added Date String so that it represents timezone of originating server
p_datestring
Amended: Barry Chase 03/01/2004
Added functionality to support binary attachments and remote attachments.
Its about 98% complete. Not work perfectly yet. Still trying to figure out
encoding to base64 or mime. Have a good start on it though.
04/12/2004
BCHASE :: Binary Support is fully functional now.
09/01/2005
BCHASE :: Modified attachment directories to use DBA_DIRECTORIES instead
of UTL_DIR in the Oracle initialization file.
02/22/2006
BCHASE :: Added variable length message email support (CLOB)
04/21/2006
BCHASE :: Expanded functionality to include Cc and Bcc
Also removed redundant calls from package. The single
mail_files command will handle flat files and binary files such as zip/pdf/etc.
SMTP Server and SMTP Server Port are parameters on the sendmail procedure now
as well.
Refer to http://home.clara.net/dwotton/dba/oracle_smtp.htm for more
details on the original source code.
For information on the enhanced mail_tools package as provided by Barry
Chase, refer to http://www.myoracleportal.com
/* Retrieves local binary file from database server.
* using DBMS_LOB commands and stores into BLOB
* return BLOB
FUNCTION get_local_binary_data (
p_dir IN VARCHAR2
, p_file IN VARCHAR2 )
RETURN BLOB;
/* Supports binary attachments and message of variable length. Uses CLOB.*/
-- DECLARE
-- t_blob BLOB;
-- BEGIN
-- Use the get_local_binary_data to collect your BLOB from the filesystem
-- or just load from a table where your BLOB is stored at, then just pass
-- as t_blob on the binaryfile parameter below. Remember to provide an
-- appropriate filename. Optionally, you can leave filename NULL and pass
-- the binaryfile parameter as EMPTY_BLOB() to send an email without an
-- attachment.
-- t_blob :=
-- mail_tools.get_local_binary_data
-- ( p_dir => 'INTF0047_TABLES'
--, p_file => 'test_file1.csv' );
-- mail_tools.sendmail
-- ( smtp_server => 'your.smtp.server'
-- , smtp_server_port => 25
-- , from_name => 'Email Address of Sender'
-- , to_name => 'list of TO email addresses separated by commas (,)'
-- , cc_name => 'list of CC email addresses separated by commas (,)'
-- , bcc_name => 'list of BCC email addresses separated by commas (,)'
-- , subject => 'Some brief Subject'
-- , MESSAGE => 'Your message goes here. Can include HTML code.'
-- , priority => '1-5 1 being the highest priority and 3 normal priority'
-- , filename => 'your.filename.txt or leave NULL'
-- , binaryfile => 'your blob is passed here otherwise leave as EMPTY_BLOB()
-- , DEBUG => 'Default is DBMS output otherwise pass a 1 to disable );
-- END;
PROCEDURE sendmail (
smtp_server VARCHAR2
, smtp_server_port PLS_INTEGER DEFAULT 25
, from_name VARCHAR2
, to_name VARCHAR2
, cc_name VARCHAR2 DEFAULT NULL
, bcc_name VARCHAR2 DEFAULT NULL
, subject VARCHAR2
, MESSAGE CLOB
, priority PLS_INTEGER DEFAULT NULL
, filename VARCHAR2 DEFAULT NULL
, binaryfile BLOB DEFAULT EMPTY_BLOB ( )
, DEBUG NUMBER DEFAULT 0 );
v_parm_value VARCHAR2 ( 4000 );
lbok BOOLEAN;
v_smtp_server VARCHAR2 ( 50 );
v_smtp_server_port NUMBER := 25;
crlf VARCHAR2 ( 10 ) := utl_tcp.crlf;
conn utl_tcp.connection;
p_debug_marker PLS_INTEGER := 0;
rc INTEGER;
p_from_name VARCHAR2 ( 100 );
p_to_name VARCHAR2 ( 4000 );
p_cc_name VARCHAR2 ( 4000 );
p_bcc_name VARCHAR2 ( 4000 );
p_subject VARCHAR2 ( 150 );
tx_timeout PLS_INTEGER := 240;
-- 240 Seconds (4 minutes);
p_datestring VARCHAR2 ( 100 )
:= 'Date: '
|| TO_CHAR ( SYSDATE, 'MM/DD/RR HH:MI AM' )
|| ' '
|| DBTIMEZONE
|| ' '
|| '(GMT'
|| DBTIMEZONE
|| ')';
-- Customize the signature that will appear in the email's MIME header.
-- Useful for versioning.
mailer_id CONSTANT VARCHAR2 ( 256 ) := 'Mailer by Oracle UTL_TCP';
max_base64_line_width CONSTANT PLS_INTEGER := 76 / 4 * 3;
END;
CREATE OR REPLACE PACKAGE BODY mail_tools
IS
PROCEDURE print_output (
p_message IN VARCHAR2 )
IS
BEGIN
dbms_output.put_line ( SUBSTR ( p_message
, 1
, 250 ));
IF LENGTH ( p_message ) > 250
THEN
dbms_output.put_line ( SUBSTR ( p_message
, 251
, 500 ));
END IF;
IF LENGTH ( p_message ) > 500
THEN
dbms_output.put_line ( SUBSTR ( p_message
, 501
, 750 ));
END IF;
IF LENGTH ( p_message ) > 750
THEN
dbms_output.put_line ( SUBSTR ( p_message
, 751
, 1000 ));
END IF;
EXCEPTION
WHEN OTHERS
THEN
NULL; -- Ignore errors... protect buffer overflow's etc.
END print_output;
FUNCTION dump_flatfile (
p_query IN VARCHAR2
, p_dir IN VARCHAR2
, p_filename IN VARCHAR2
, p_separator IN VARCHAR2
, p_headers IN BOOLEAN DEFAULT FALSE
, p_trailing_separator IN BOOLEAN DEFAULT FALSE
, p_max_linesize IN NUMBER DEFAULT 32000
, p_mode IN VARCHAR2 DEFAULT 'w' )
RETURN NUMBER
IS
l_output utl_file.file_type;
l_thecursor INTEGER DEFAULT dbms_sql.open_cursor;
l_columnvalue VARCHAR2 ( 4000 );
l_status INTEGER;
l_colcnt NUMBER DEFAULT 0;
l_cnt NUMBER DEFAULT 0;
l_separator VARCHAR2 ( 10 ) DEFAULT '';
l_line LONG;
l_desctbl dbms_sql.desc_tab;
v_sqlerrm VARCHAR2 ( 32000 );
l_mode CHAR ( 1 ) := 'w';
BEGIN
IF p_mode NOT IN ( 'w', 'a' )
THEN
l_mode := 'w';
ELSE
l_mode := p_mode;
END IF;
l_output := utl_file.fopen ( p_dir
, p_filename
, l_mode
, p_max_linesize );
dbms_sql.parse ( l_thecursor
, p_query
, dbms_sql.native );
dbms_sql.describe_columns ( l_thecursor
, l_colcnt
, l_desctbl );
FOR i IN 1 .. l_colcnt
LOOP
dbms_sql.define_column ( l_thecursor
, i
, l_columnvalue
, 4000 );
IF ( l_desctbl ( i ).col_type = 2 ) /* number type */
THEN
l_desctbl ( i ).col_max_len := l_desctbl ( i ).col_precision + 2;
ELSIF ( l_desctbl ( i ).col_type = 12 ) /* date type */
THEN
/* length of my date format */
l_desctbl ( i ).col_max_len := 20;
ELSIF ( l_desctbl ( i ).col_type = 8 ) /* LONG type */
THEN
l_desctbl ( i ).col_max_len := 2000;
END IF;
IF p_headers
THEN
utl_file.put ( l_output, l_separator || l_desctbl ( i ).col_name );
l_separator := p_separator;
END IF;
END LOOP;
IF p_trailing_separator
THEN
utl_file.put ( l_output, l_separator );
END IF;
IF p_headers
THEN
utl_file.new_line ( l_output );
END IF;
l_status := dbms_sql.EXECUTE ( l_thecursor );
LOOP
EXIT WHEN ( dbms_sql.fetch_rows ( l_thecursor ) <= 0 );
l_line := NULL;
l_separator := '';
FOR i IN 1 .. l_colcnt
LOOP
dbms_sql.COLUMN_VALUE ( l_thecursor
, i
, l_columnvalue );
IF NVL ( INSTR ( l_columnvalue, ',' ), 0 ) = 0
THEN
NULL;
ELSE
l_columnvalue := '"' || l_columnvalue || '"';
END IF;
utl_file.put ( l_output, l_separator || l_columnvalue );
l_separator := p_separator;
END LOOP;
IF p_trailing_separator
THEN
utl_file.put ( l_output, l_separator );
END IF;
utl_file.new_line ( l_output );
l_cnt := l_cnt + 1;
END LOOP;
dbms_sql.close_cursor ( l_thecursor );
utl_file.fclose ( l_output );
RETURN l_cnt;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
dbms_output.put_line ( 'NO_DATA_FOUND' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_path
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_PATH' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.read_error
THEN
dbms_output.put_line ( 'UTL_FILE.READ_ERROR' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.write_error
THEN
dbms_output.put_line ( 'UTL_FILE.WRITE_ERROR' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_mode
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_MODE' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_filehandle
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_FILEHANDLE' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_operation
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_OPERATION' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.internal_error
THEN
dbms_output.put_line ( 'UTL_FILE.INTERNAL_ERROR' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN utl_file.invalid_maxlinesize
THEN
dbms_output.put_line ( 'UTL_FILE.INVALID_MAXLINESIZE' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN VALUE_ERROR
THEN
dbms_output.put_line ( 'UTL_FILE.VALUE_ERROR' );
utl_file.fclose ( l_output );
RETURN l_cnt;
WHEN OTHERS
THEN
hum_do.default_exception ( 'ERROR in dump_csv : ' );
utl_file.fclose ( l_output );
RETURN l_cnt;
END dump_flatfile;
-- Return the next email address in the list of email addresses, separated
-- by either a "," or a ";". The format of mailbox may be in one of these:
-- someone@some-domain
-- "Someone at some domain" <someone@some-domain>
-- Someone at some domain <someone@some-domain>
FUNCTION get_mail_address (
addr_list IN OUT VARCHAR2 )
RETURN VARCHAR2
IS
addr VARCHAR2 ( 256 );
i PLS_INTEGER;
FUNCTION lookup_unquoted_char (
str IN VARCHAR2
, chrs IN VARCHAR2 )
RETURN PLS_INTEGER
AS
c VARCHAR2 ( 5 );
i PLS_INTEGER;
len PLS_INTEGER;
inside_quote BOOLEAN;
BEGIN
inside_quote := FALSE;
i := 1;
len := LENGTH ( str );
WHILE ( i <= len )
LOOP
c := SUBSTR ( str
, i
, 1 );
IF ( inside_quote )
THEN
IF ( c = '"' )
THEN
inside_quote := FALSE;
ELSIF ( c = '\' )
THEN
i := i + 1;
-- Skip the quote character
END IF;
GOTO next_char;
END IF;
IF ( c = '"' )
THEN
inside_quote := TRUE;
GOTO next_char;
END IF;
IF ( INSTR ( chrs, c ) >= 1 )
THEN
RETURN i;
END IF;
<<next_char>>
i := i + 1;
END LOOP;
RETURN 0;
END;
BEGIN
addr_list := LTRIM ( addr_list );
i := lookup_unquoted_char ( addr_list, ',;' );
IF ( i >= 1 )
THEN
addr := SUBSTR ( addr_list
, 1
, i - 1 );
addr_list := SUBSTR ( addr_list, i + 1 );
ELSE
addr := addr_list;
addr_list := '';
END IF;
i := lookup_unquoted_char ( addr, '<' );
IF ( i >= 1 )
THEN
addr := SUBSTR ( addr, i + 1 );
i := INSTR ( addr, '>' );
IF ( i >= 1 )
THEN
addr := SUBSTR ( addr
, 1
, i - 1 );
END IF;
END IF;
RETURN addr;
END;
FUNCTION smtp_command (
command IN VARCHAR2
, ok IN VARCHAR2 DEFAULT '250'
, code OUT VARCHAR2
, DEBUG NUMBER DEFAULT 0 )
RETURN BOOLEAN
IS
response VARCHAR2 ( 3 );
p_output_message VARCHAR2 ( 255 );
len PLS_INTEGER;
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
len := utl_tcp.write_line ( conn, command );
p_output_message := SUBSTR ( utl_tcp.get_line ( conn, TRUE )
, 1
, 255 );
response := SUBSTR ( p_output_message
, 1
, 3 );
p_output_message :=
SUBSTR ( command || ' - ' || p_output_message
, 1
, 255 );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
IF ( response <> ok )
THEN
code := response;
RETURN FALSE;
ELSE
code := response;
RETURN TRUE;
END IF;
EXCEPTION
WHEN OTHERS
THEN
p_output_message := SQLCODE || ' - ' || SQLERRM;
code := p_output_message;
RETURN FALSE;
END smtp_command;
FUNCTION query_server (
smtp_server VARCHAR2
, smtp_server_port PLS_INTEGER DEFAULT 25
, DEBUG NUMBER DEFAULT 0 )
RETURN BOOLEAN
IS
p_output_message VARCHAR2 ( 255 );
PRAGMA AUTONOMOUS_TRANSACTION;
err_noop EXCEPTION; -- SMTP code 250 not received
err_server_reject EXCEPTION;
-- SMTP code 421 means rejected
BEGIN
v_smtp_server := smtp_server;
v_smtp_server_port := smtp_server_port;
-- Open the SMTP connection ...
conn :=
utl_tcp.open_connection ( remote_host => v_smtp_server
, remote_port => v_smtp_server_port
, tx_timeout => tx_timeout );
----- OPEN SMTP PORT CONNECTION
rc := utl_tcp.write_line ( conn, 'HELO ' || v_smtp_server );
-- This will return a 250 OK response if your connection is valid
-- Initial handshaking ...
----- PERFORMS HANDSHAKING WITH SMTP SERVER
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
IF SUBSTR ( p_output_message
, 1
, 3 ) = '421'
THEN
RAISE err_server_reject;
END IF;
-- NOOP THE SERVER
rc := utl_tcp.write_line ( conn, 'NOOP' );
-- This will return a 250 OK response if your connection is valid
-- Initial handshaking ...
----- PERFORMS NOOP WITH SMTP SERVER
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
IF SUBSTR ( p_output_message
, 1
, 3 ) <> '250'
THEN
RAISE err_noop;
END IF;
rc := utl_tcp.write_line ( conn, 'QUIT' );
----- ENDS EMAIL TRANSACTION
BEGIN
FOR i_idx IN 1 .. 100
LOOP
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
END;
utl_tcp.close_connection ( conn ); ----- CLOSE SMTP PORT CONNECTION
RETURN TRUE;
EXCEPTION
WHEN err_server_reject
THEN
print_output ( 'ERROR -'
|| ' Server Rejected Connection ::'
|| ' SERVER_MSG := '
|| p_output_message );
RETURN FALSE;
WHEN err_noop
THEN
print_output ( 'ERROR -'
|| ' NOOP Check Failed ::'
|| ' SERVER_MSG := '
|| p_output_message );
utl_tcp.close_connection ( conn ); ----- CLOSE SMTP PORT CONNECTION
RETURN FALSE;
END query_server;
FUNCTION get_local_binary_data (
p_dir IN VARCHAR2
, p_file IN VARCHAR2 )
RETURN BLOB
IS
l_bfile BFILE;
l_data BLOB;
l_dbdir VARCHAR2 ( 100 ) := p_dir;
BEGIN
dbms_lob.createtemporary ( lob_loc => l_data
, CACHE => TRUE
, dur => dbms_lob.CALL );
l_bfile := BFILENAME ( l_dbdir, p_file );
dbms_lob.fileopen ( l_bfile, dbms_lob.file_readonly );
dbms_lob.loadfromfile ( l_data
, l_bfile
, dbms_lob.getlength ( l_bfile ));
dbms_lob.fileclose ( l_bfile );
RETURN l_data;
EXCEPTION
WHEN OTHERS
THEN
print_output ( 'Error during GET_LOCAL_BINARY_DATA :: '
|| SQLCODE
|| ' - '
|| SQLERRM );
dbms_lob.fileclose ( l_bfile );
RAISE;
END get_local_binary_data;
PROCEDURE attach_base64 (
conn IN OUT NOCOPY utl_tcp.connection
, DATA IN BLOB )
IS
i PLS_INTEGER;
len PLS_INTEGER;
l_result PLS_INTEGER;
l_buffer RAW ( 32767 );
l_pos INTEGER := 1;
l_blob_len INTEGER;
l_amount BINARY_INTEGER := 32767;
req utl_http.req;
resp utl_http.resp;
pdata RAW ( 200 );
BEGIN
-- Split the Base64-encoded attachment into multiple lines
-- In writing Base-64 encoded text following the MIME format below,
-- the MIME format requires that a long piece of data must be splitted
-- into multiple lines and each line of encoded data cannot exceed
-- 80 characters, including the new-line characters. Also, when
-- splitting the original data into pieces, the length of each chunk
-- of data before encoding must be a multiple of 3, except for the
-- last chunk. The constant MAX_BASE64_LINE_WIDTH
-- (76 / 4 * 3 = 57) is the maximum length (in bytes) of each chunk
-- of data before encoding.
l_blob_len := dbms_lob.getlength ( DATA );
WHILE l_pos < l_blob_len
LOOP
l_amount := max_base64_line_width;
dbms_lob.READ ( DATA
, l_amount
, l_pos
, l_buffer );
rc := utl_tcp.write_raw ( conn, utl_encode.base64_encode ( l_buffer ));
utl_tcp.FLUSH ( conn );
l_pos := l_pos + max_base64_line_width;
rc := utl_tcp.write_line ( conn, crlf );
END LOOP;
END attach_base64;
PROCEDURE sendmail (
smtp_server VARCHAR2
, smtp_server_port PLS_INTEGER DEFAULT 25
, from_name VARCHAR2
, to_name VARCHAR2
, cc_name VARCHAR2 DEFAULT NULL
, bcc_name VARCHAR2 DEFAULT NULL
, subject VARCHAR2
, MESSAGE CLOB
, priority PLS_INTEGER DEFAULT NULL
, filename VARCHAR2 DEFAULT NULL
, binaryfile BLOB DEFAULT EMPTY_BLOB ( )
, DEBUG NUMBER DEFAULT 0 )
IS
pos PLS_INTEGER := 1;
bytes_o_data CONSTANT PLS_INTEGER := 32767;
offset PLS_INTEGER := bytes_o_data;
msg_length CONSTANT PLS_INTEGER
:= dbms_lob.getlength ( MESSAGE );
v_line VARCHAR2 ( 32767 );
i BINARY_INTEGER;
v_slash_pos NUMBER;
my_recipients VARCHAR2 ( 32767 );
p_recipient_count PLS_INTEGER := 0;
p_output_message VARCHAR2 ( 2000 );
PRAGMA AUTONOMOUS_TRANSACTION;
err_server_reject EXCEPTION;
-- SMTP code 421 means rejected
err_message_send EXCEPTION; -- SMTP code must be 250
err_end_of_input EXCEPTION;
-- Used to signify last line of input retrieved
l_result PLS_INTEGER;
l_buffer_b RAW ( 32767 );
l_amount BINARY_INTEGER := 32767;
l_pos INTEGER := 1;
l_blob_len INTEGER;
l_blob BLOB;
g_debug BOOLEAN := TRUE;
i_base64 PLS_INTEGER;
len_base64 PLS_INTEGER;
BEGIN
v_smtp_server := smtp_server;
v_smtp_server_port := smtp_server_port;
l_blob := binaryfile;
-- Open the SMTP connection ...
conn :=
utl_tcp.open_connection ( remote_host => v_smtp_server
, remote_port => v_smtp_server_port
, tx_timeout => tx_timeout );
----- OPEN SMTP PORT CONNECTION
rc := utl_tcp.write_line ( conn, 'HELO ' || v_smtp_server );
-- Initial handshaking ...
----- PERFORMS HANDSHAKING WITH SMTP SERVER
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
IF SUBSTR ( p_output_message
, 1
, 3 ) = '421'
THEN
RAISE err_server_reject;
ELSE
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
rc := utl_tcp.write_line ( conn, 'MAIL FROM: ' || from_name );
----- MBOX SENDING THE EMAIL
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
-- rc := UTL_TCP.write_line (conn, 'RCPT TO: ' || to_name);
-- Specify recipient(s) of the email.
my_recipients := to_name;
WHILE ( my_recipients IS NOT NULL )
LOOP
BEGIN
rc :=
utl_tcp.write_line ( conn
, 'RCPT TO: '
|| get_mail_address ( my_recipients ));
p_recipient_count := p_recipient_count + 1;
END;
END LOOP;
-- DBMS_OUTPUT.put_line ('RCPT TO: COUNT ' || p_recipient_count);
----- MBOX RECV THE EMAIL
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
-- rc := UTL_TCP.write_line (conn, 'RCPT TO: ' || cc_name);
-- Specify cc recipient(s) of the email.
my_recipients := cc_name;
WHILE ( my_recipients IS NOT NULL )
LOOP
BEGIN
rc :=
utl_tcp.write_line ( conn
, 'RCPT TO: '
|| get_mail_address ( my_recipients ));
p_recipient_count := p_recipient_count + 1;
END;
END LOOP;
-- DBMS_OUTPUT.put_line ('RCPT TO: COUNT ' || p_recipient_count);
----- MBOX RECV THE EMAIL
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
-- rc := UTL_TCP.write_line (conn, 'RCPT TO: ' || bcc_name);
-- Specify bcc recipient(s) of the email.
my_recipients := bcc_name;
WHILE ( my_recipients IS NOT NULL )
LOOP
BEGIN
rc :=
utl_tcp.write_line ( conn
, 'RCPT TO: '
|| get_mail_address ( my_recipients ));
p_recipient_count := p_recipient_count + 1;
END;
END LOOP;
-- DBMS_OUTPUT.put_line ('RCPT TO: COUNT ' || p_recipient_count);
----- MBOX RECV THE EMAIL
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
rc := utl_tcp.write_line ( conn, 'DATA' );
----- EMAIL MSG BODY START
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
-- build the start of the mail message ...
rc := utl_tcp.write_line ( conn, p_datestring );
rc := utl_tcp.write_line ( conn, 'From: ' || from_name );
rc := utl_tcp.write_line ( conn, 'Subject: ' || subject );
rc := utl_tcp.write_line ( conn, 'To: ' || to_name );
IF cc_name IS NOT NULL
THEN
rc := utl_tcp.write_line ( conn, 'Cc: ' || cc_name );
END IF;
IF bcc_name IS NOT NULL
THEN
rc := utl_tcp.write_line ( conn, 'Bcc: ' || bcc_name );
END IF;
rc := utl_tcp.write_line ( conn, 'Mime-Version: 1.0' );
-- Set priority:
-- High Normal Low
-- 1 2 3 4 5
IF ( priority IS NOT NULL )
THEN
rc := utl_tcp.write_line ( conn, 'X-Priority: ' || priority );
END IF;
rc := utl_tcp.write_line ( conn, 'X-Mailer: ' || mailer_id );
rc :=
utl_tcp.write_line
( conn
, 'Content-Type: multipart/mixed; boundary="=_mixed 0052287A85256E75_="' );
rc := utl_tcp.write_line ( conn, '' );
rc :=
utl_tcp.write_line
( conn
, 'This is a Mime message, which your current mail reader may not' );
rc :=
utl_tcp.write_line
( conn
, 'understand. Parts of the message will appear as text. If the remainder' );
rc :=
utl_tcp.write_line
( conn
, 'appears as random characters in the message body, instead of as' );
rc :=
utl_tcp.write_line
( conn
, 'attachments, then you''ll have to extract these parts and decode them' );
rc := utl_tcp.write_line ( conn, 'manually.' );
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, '--=_mixed 0052287A85256E75_=' );
rc :=
utl_tcp.write_line ( conn
, 'Content-Type: text/html; charset=8859-1' );
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, '<html>' );
rc := utl_tcp.write_line ( conn, '<head>' );
rc :=
utl_tcp.write_line
( conn
, '<meta http-equiv="Content-Type" content="text/html;charset=8859-1">' );
rc := utl_tcp.write_line ( conn, '<title>' );
rc := utl_tcp.write_line ( conn, subject );
rc := utl_tcp.write_line ( conn, '</title>' );
rc := utl_tcp.write_line ( conn, '</head>' );
rc := utl_tcp.write_line ( conn, '<body>' );
WHILE pos < msg_length
LOOP
rc :=
utl_tcp.write_line ( conn
, dbms_lob.SUBSTR ( MESSAGE
, offset
, pos ));
pos := pos + offset;
offset := LEAST ( bytes_o_data, msg_length - offset );
END LOOP;
rc := utl_tcp.write_line ( conn, '<BR><BR>' );
rc := utl_tcp.write_line ( conn, '</body></html>' );
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, crlf );
-- Append the file BLOB ...
-- If the filename has been supplied ... it will fail if the BLOB is empty
IF filename IS NOT NULL
THEN
BEGIN
-- generate the MIME boundary line ...
rc :=
utl_tcp.write_line ( conn, '--=_mixed 0052287A85256E75_=' );
rc :=
utl_tcp.write_line
( conn
, 'Content-Type: application/octet-stream; name="'
|| filename
|| '"' );
rc :=
utl_tcp.write_line
( conn
, 'Content-Disposition: attachment; filename="'
|| filename
|| '"' );
rc :=
utl_tcp.write_line ( conn
, 'Content-Transfer-Encoding: base64' );
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, '' );
-- and append the file contents to the end of the message ...
-- Go get the file and the loop through blob and attach data
-- and append the file contents to the end of the message ...
attach_base64 ( conn => conn
, DATA => l_blob );
EXCEPTION
WHEN OTHERS
THEN
p_output_message :=
'Error in attaching file '
|| filename
|| ' :: '
|| SQLCODE
|| ' - '
|| SQLERRM;
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
RAISE err_message_send;
END;
END IF;
rc := utl_tcp.write_line ( conn, '' );
-- append the final boundary line ...
rc := utl_tcp.write_line ( conn, '' );
rc := utl_tcp.write_line ( conn, '--=_mixed 0052287A85256E75_=--' );
rc := utl_tcp.write_line ( conn, '' );
-- and close the SMTP connection ...
rc := utl_tcp.write_line ( conn, '.' );
----- EMAIL MESSAGE BODY END
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
-- DBMS_OUTPUT.put_line (UTL_TCP.get_line (conn, TRUE));
rc := utl_tcp.write_line ( conn, 'QUIT' );
----- ENDS EMAIL TRANSACTION
p_output_message := utl_tcp.get_line ( conn, TRUE );
-- Capture '.' Message sent dialog
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
BEGIN
FOR i_idx IN 1 .. 100
LOOP
p_output_message := utl_tcp.get_line ( conn, TRUE );
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
IF DEBUG = 1
THEN -- No Output
NULL;
ELSE -- Then DBMS_OUTPUT messages
print_output ( p_output_message );
END IF;
END;
END IF; -- err_server_reject
utl_tcp.close_connection ( conn ); ----- CLOSE SMTP PORT CONNECTION
EXCEPTION
WHEN err_message_send
THEN
print_output ( CHR ( 10 )
|| CHR ( 10 )
|| 'ERROR -'
|| ' Message was not submitted for delivery' );
print_output ( ' [FROM_NAME := ' || from_name || '] ' );
print_output ( ' [TO_NAME := ' || to_name || '] ' );
print_output ( ' [CC_NAME := ' || cc_name || '] ' );
print_output ( ' [BCC_NAME := ' || bcc_name || '] ' );
print_output ( ' [SUBJECT := ' || subject || '] ' );
print_output ( ' SERVER_MSG := ' || p_output_message );
utl_tcp.close_connection ( conn ); ----- CLOSE SMTP PORT CONNECTION
WHEN err_server_reject
THEN
print_output ( CHR ( 10 )
|| CHR ( 10 )
|| 'ERROR -'
|| ' Server Rejected Email' );
print_output ( ' [FROM_NAME := ' || from_name || '] ' );
print_output ( ' [TO_NAME := ' || to_name || '] ' );
print_output ( ' [CC_NAME := ' || cc_name || '] ' );
print_output ( ' [BCC_NAME := ' || bcc_name || '] ' );
print_output ( ' [SUBJECT := ' || subject || '] ' );
print_output ( ' SERVER_MSG := ' || p_output_message );
WHEN OTHERS
THEN
print_output ( CHR ( 10 )
|| CHR ( 10 )
|| 'ERROR :: '
|| SQLCODE
|| ' - '
|| SQLERRM );
print_output ( ' [FROM_NAME := ' || from_name || '] ' );
print_output ( ' [TO_NAME := ' || to_name || '] ' );
print_output ( ' [CC_NAME := ' || cc_name || '] ' );
print_output ( ' [BCC_NAME := ' || bcc_name || '] ' );
print_output ( ' [SUBJECT := ' || subject || '] ' );
print_output ( ' SERVER_MSG := ' || p_output_message );
END sendmail;
END;
/Perhaps your new SMTP server requires a more secure form of authentication than AUTH LOGIN. If you telnet to this new SMTP server on port 25 you should be issue the HELO or EHLO command to find out what AUTH mechanisms the server supports. You could then alter your code to use one of the supported authentication mechanisms.
-
PLS-00201 identifier must be declared
Hi All,
Can any one please help me regarding this error.
I am getting the PLS-00201 identifier tree_sorting must be declared at the line " Tree_Sorting(1, 0); ".
if i comment the " Tree_Sorting(1, 0); " at pkgfc_gi.v_cphase := '01-13'; and uncomment the " Tree_Sorting(1, 0); " at pkgfc_gi.v_cphase := '01-09' then the procedure is compiling successfully; This is my stored procedure.
Please help me in solving this.
CREATE OR REPLACE PACKAGE BODY FA_Main AS
/*-------------------------------- Calcul_FA -------------------------------*/
FUNCTION Calcul_FA (
p_client_group IN tfc_stc_client_groups.s_client_group%TYPE DEFAULT NULL,
p_admin_group IN tfc_stc_clients.c_admin_group %TYPE DEFAULT NULL,
p_client IN tfc_stc_clients.s_client %TYPE DEFAULT NULL,
p_report_group IN tfc_stc_report_groups.g_classification%TYPE DEFAULT NULL,
p_contract IN tfc_stc_contracts.s_contract %TYPE DEFAULT NULL,
p_fa_typ IN tfc_prm_fa_master.c_fa_typ %TYPE DEFAULT NULL,
p_fa IN tfc_prm_fa_master.s_fa %TYPE DEFAULT NULL,
p_beg_period IN DATE DEFAULT NULL,
p_end_period IN DATE DEFAULT NULL,
p_y_all_ok IN VARCHAR2 DEFAULT 'Y',
p_y_estimate IN VARCHAR2 DEFAULT 'N',
p_est_date IN DATE DEFAULT NULL)
RETURN NUMBER IS
----------------------------------------------------------------------- CURSEURS
-- List of FA to calculate --
CURSOR c_fa IS
SELECT pfm.s_fa s_fa, pfm.c_fa_typ c_fa_typ, sct.s_contract s_contract, srg.g_classification g_classification,
scl.s_client s_client, scl.c_admin_group c_admin_group, scg.s_client_group s_client_group
FROM tfc_prm_fa_master pfm, tfc_stc_contracts sct, tfc_stc_clients scl, tfc_stc_client_groups scg, tfc_stc_report_groups srg
WHERE pfm.c_fa_structure_typ = 'PARM'
AND ((p_fa IS NOT NULL AND pfm.s_fa = p_fa ) OR p_fa IS NULL)
AND ((p_fa_typ IS NOT NULL AND pfm.c_fa_typ = p_fa_typ ) OR p_fa_typ IS NULL)
AND ((p_contract IS NOT NULL AND sct.s_contract = p_contract ) OR p_contract IS NULL)
AND ((p_report_group IS NOT NULL AND srg.g_classification LIKE p_report_group||'%') OR p_report_group IS NULL)
AND ((p_client IS NOT NULL AND scl.s_client = p_client ) OR p_client IS NULL)
AND ((p_admin_group IS NOT NULL AND scl.c_admin_group = p_admin_group ) OR p_admin_group IS NULL)
AND ((p_client_group IS NOT NULL AND scg.s_client_group = p_client_group ) OR p_client_group IS NULL)
AND (NVL(p_client_group,NVL(p_client,NVL(p_contract, p_fa))) IS NOT NULL OR p_admin_group IS NOT NULL OR p_report_group IS NOT NULL)
AND (p_beg_period IS NULL OR ((p_beg_period IS NOT NULL AND pfm.d_first_calculation IS NOT NULL AND p_beg_period >= pfm.d_first_calculation) OR pfm.d_first_calculation IS NULL))
AND (p_end_period IS NULL OR ((p_end_period IS NOT NULL AND pfm.d_end_calculation IS NOT NULL AND p_end_period <= pfm.d_end_calculation) OR pfm.d_end_calculation IS NULL) OR (p_end_period IS NOT NULL AND sct.d_inception <= p_end_period ))
AND sct.s_contract = pfm.fk_contract
AND scl.s_client = sct.fk_client
AND scg.s_client_group (+)= scl.fk_client_group
AND srg.s_report_group (+)= sct.fk_report_group
AND pfm.y_fee_to_calculate = 'Y'
AND sct.c_contract_status = 'ACTIVE'
AND ROWNUM < 2;
BEGIN
COMMIT;
IF pkgfc_faed.v_y_estimate = 'Y' THEN
INSERT INTO tfc_log_application_master (
s_log, l_log,
d_t_begin_task,
c_application_task, c_task_status,
g_key_0, g_key_1,
g_key_2, g_key_3,
g_key_4, g_key_5,
g_key_6, g_key_7,
g_key_8, g_key_9)
VALUES (
pkgfc_faed.v_s_log, v_l_log, SysDate,
'ESTIMATE', 'RUNNING',
TRIM(TO_CHAR(p_client_group)), p_admin_group,
TRIM(TO_CHAR(p_client)), p_report_group,
TRIM(TO_CHAR(p_contract)), p_fa_typ,
TRIM(TO_CHAR(p_fa)), TO_CHAR(p_beg_period,'DD/MM/YYYY'),
TO_CHAR(p_end_period,'DD/MM/YYYY'), v_y_all_ok);
ELSE
INSERT INTO tfc_log_application_master (
s_log, l_log,
d_t_begin_task,
c_application_task, c_task_status,
g_key_0, g_key_1,
g_key_2, g_key_3,
g_key_4, g_key_5,
g_key_6, g_key_7,
g_key_8, g_key_9)
VALUES (
pkgfc_faed.v_s_log, v_l_log,
SysDate,
'CALCULATION', 'RUNNING',
TRIM(TO_CHAR(p_client_group)), p_admin_group,
TRIM(TO_CHAR(p_client)), p_report_group,
TRIM(TO_CHAR(p_contract)), p_fa_typ,
TRIM(TO_CHAR(p_fa)), TO_CHAR(p_beg_period,'DD/MM/YYYY'),
TO_CHAR(p_end_period,'DD/MM/YYYY'), v_y_all_ok);
END IF;
v_return := pkgfc_faed.v_s_log;
COMMIT;
-- Loop on all Fee/Alloc to calculate --
-- Added by Santhakumar
BEGIN
INSERT INTO tmp_prm_fa_details(
SELECT USERENV('SESSIONID') SESSION_ID,
LEVEL CUR_LEVEL,
(CASE WHEN (SELECT MAX(LEVEL)
FROM tfc_prm_fa_details fad2
WHERE fad2.fk_fa = fad1.fk_fa
START WITH fad2.s_fa_detail=fad1.s_fa_detail
CONNECT BY PRIOR fad2.s_fa_detail = fad2.fk_fa_detail_upper_level) > 1
THEN LEVEL + 1
ELSE LEVEL
END) NEXT_LEVEL,
fad1.s_fa_detail,
fad1.fk_fee_alloc_detail,
fad1.fk_fa,
fad1.l_fa_detail,
fad1.g_fa_4calculation,
fad1.fk_fa_detail_upper_level,
fad1.fk_third_party,
fad1.g_consolidation_rule,
fad1.c_fa_calculation_typ,
fad1.fk_aggregation_rule,
fad1.fk_scale,
fad1.g_scale_band_unit,
fad1.g_value,
fad1.n_detail_order,
fad1.y_ref_amount_equal_total_aum,
fad1.c_validation_status,
fad1.g_val_by,
fad1.d_t_val,
fad1.g_ins_by,
fad1.d_t_ins,
fad1.g_upd_by,
fad1.d_t_upd
FROM tfc_prm_fa_details fad1
START WITH fad1.fk_fa_detail_upper_level IS NULL
CONNECT BY PRIOR fad1.s_fa_detail = fad1.fk_fa_detail_upper_level
END;
-- Added by Santhakumar
pkgfc_gi.v_cphase := '00-02';
FOR v_fa IN c_fa LOOP
pkgfc_gi.v_cphase := '01-08';
DECLARE
-- Tree Sorting Recursive Procedure --
PROCEDURE Tree_Sorting (p_level IN NUMBER,p_fk_fa_detail_upper_level IN NUMBER) IS
-- Cursor to retrieve data at current level --
CURSOR c_tfd IS
SELECT *
FROM tfc_tmp_fa_details tfd
WHERE tfd.fk_fa = v_fa.s_fa
AND tfd.session_id = USERENV('SESSIONID')
AND tfd.cur_level = p_level
AND tfd.fk_fa_detail_upper_level = p_fk_fa_detail_upper_level
ORDER BY tfd.n_detail_order ASC;
Error_Found_in_Tree_Sorting EXCEPTION;
-------------------------------------------------------------------------- BEGIN
BEGIN
FOR v_tfd IN c_tfd LOOP
pkgfc_dts.put_nline('Level : '||TO_CHAR(v_tfd.cur_level)||' - '||v_tfd.g_fa_4calculation||' - '||TO_CHAR(p_fk_fa_detail_upper_level));
pkgfc_gi.v_cphase := '01-14';
pkgfc_faed.v_nb_fa_det := pkgfc_faed.v_nb_fa_det + 1;
pkgfc_faed.v_fa_details(pkgfc_faed.v_nb_fa_det) := v_tfd;
pkgfc_faed.v_nb_max_level := GREATEST(pkgfc_faed.v_nb_max_level,
pkgfc_faed.v_fa_details(pkgfc_faed.v_nb_fa_det).cur_level);
-- Break the link with Root Record --
IF (pkgfc_faed.v_fa_details(pkgfc_faed.v_nb_fa_det).fk_fa_detail_upper_level = 0) THEN
pkgfc_faed.v_fa_details(pkgfc_faed.v_nb_fa_det).fk_fa_detail_upper_level := NULL;
END IF;
IF (v_tfd.cur_level < v_tfd.next_level) THEN
pkgfc_gi.v_cphase := '01-15';
Tree_Sorting(v_tfd.next_level, v_tfd.s_fa_detail);
END IF;
IF (pkgfc_gi.v_cretour <> '0') THEN
RAISE Error_Found_in_Tree_Sorting;
END IF;
END LOOP;
---------------------------------------------------------------------- EXCEPTION
EXCEPTION
WHEN Error_Found_in_Tree_Sorting THEN
IF (c_tfd%ISOPEN ) THEN CLOSE c_tfd ; END IF;
WHEN OTHERS THEN
IF (c_tfd%ISOPEN ) THEN CLOSE c_tfd ; END IF;
pkgfc_gi.v_cretour := '9'; -- When Others Error
pkgfc_gi.v_cproc := 'FA_Engine_Main.Tree_Sorting';
pkgfc_gi.v_mess := SUBSTR(SQLERRM(SQLCODE), 1, 255);
pkgfc_dts.put_nline('Err : '||pkgfc_gi.v_cretour||' - '||pkgfc_gi.v_cphase||' - '||pkgfc_gi.v_cproc||' - '||pkgfc_gi.v_mess);
---------------------------------------------------------------------------- END
END Tree_Sorting;
PROCEDURE Autonomous_0108 IS
PRAGMA AUTONOMOUS_TRANSACTION; -- Permit Commit/Rollback independently of the current transaction
BEGIN
-- Clean Temporary Table --
pkgfc_gi.v_cphase := '01-09';
DELETE tfc_tmp_fa_details WHERE session_id NOT IN (SELECT DISTINCT audsid FROM all_sessions);
COMMIT;
--Tree_Sorting(1, 0);
END Autonomous_0108;
BEGIN
Autonomous_0108;
END;
-- Get FA Details from Prm_Fa_Details --
pkgfc_gi.v_cphase := '01-10';
select count(1) into v_num from tfc_tmp_fa_details;
Dbms_output.put_line('first' || v_num);
Dbms_output.put_line('Session Id --> ' || USERENV('SESSIONID'));
INSERT INTO tfc_tmp_fa_details (SELECT * FROM tmp_prm_fa_details WHERE fk_fa = v_fa.s_fa);
-- Insert a Root Record for Tree Sorting purpose --
pkgfc_gi.v_cphase := '01-11';
INSERT INTO tfc_tmp_fa_details (
session_id, cur_level, next_level,
s_fa_detail, fk_fa, fk_fa_detail_upper_level)
VALUES (
USERENV('SESSIONID'), 0, 1,
0, v_fa.s_fa, NULL);
-- Link the Level 1 with Root Level (0) --
pkgfc_gi.v_cphase := '01-12';
UPDATE tfc_tmp_fa_details
SET fk_fa_detail_upper_level = NVL(fk_fa_detail_upper_level, 0)
WHERE fk_fa = v_fa.s_fa
AND s_fa_detail > 0
AND session_id = USERENV('SESSIONID');
-- Sort FA Details Tree according n_detail_order field --
pkgfc_gi.v_cphase := '01-13';
Tree_Sorting(1, 0);
-- Clean Temporary Table --
pkgfc_gi.v_cphase := '01-16';
WHEN OTHERS THEN
dbms_output.put_line('OTHERS');
pkgfc_gi.eev_cur := v_eev_cur;
v_loop_ret := -1;
IF (c_fa%ISOPEN ) THEN CLOSE c_fa ; END IF;
IF (c_cli%ISOPEN) THEN CLOSE c_cli; END IF;
IF (c_ctr%ISOPEN) THEN CLOSE c_ctr; END IF;
IF (c_fam%ISOPEN) THEN CLOSE c_fam; END IF;
IF (c_cad%ISOPEN) THEN CLOSE c_cad; END IF;
IF (c_fad%ISOPEN) THEN CLOSE c_fad; END IF;
pkgfc_gi.v_cretour := '9'; -- When Others Error
pkgfc_gi.v_cproc := 'FA_Engine_Main.Calcul_FA';
pkgfc_gi.v_mess := SUBSTR(SQLERRM(SQLCODE), 1, 255);
pkgfc_dts.put_nline('Err : '||pkgfc_gi.v_cretour||' - '||pkgfc_gi.v_cphase||' - '||pkgfc_gi.v_cproc||' - '||pkgfc_gi.v_mess);
-------------------------------------------------------------------- END
END;
END LOOP;
return(v_return);
END Calcul_FA;
END FA_Main;
/It looks to me like procedure 'tree_sorting' is declared as a local procedure within a nested BEGIN .. END block (which spans lines 288 - 438). You cannot call this procedure outside that block, it is out of scope - you would have to move it to a higher scope.
It would help if you posted something remotely readable in future. -
Getting all of the NEW values from a trigger to store as XML CLOB
Our custom system has a number of tables which are given to us from a centralized reference data system. When data is incorrect or missing, the users have the ability to enter in a change request to the data.
We are looking at storing these changes as XML in CLOB colums to make the storage of the requests more generic. I was given this to work with:
SELECT value(em).getClobVal() AS "XMLTYPE"
FROM table(XMLSequence(Cursor(SELECT *
FROM TABLE_A
WHERE X=WHATEVER))) em;
Now that will give me an XML row for each return row. The problem is, I'm placing this in an AFTER INSERT TRIGGER so I cannot SELECT from the table, I can only use the values as passed in the REFERENCING section.
My problem is, I'd like to make this as generic as possible so I don't have to lay out the columns individually for each table we institute this on (there's about 70 of them).
I'm not sure if I'm explaining this well enough. This is on 10gR2. What I'm ultimately looking for is a generic way to take a row that was just inserted into a table, wrap it in XML tags corresponding to the column name and then insert that info into a CLOB in another table.hi vittorio
i have a solution but im very sure it is not exact answer to your question . it will definitely help you .
create table temp_type as select * from emp where 1 = 2;
create or replace procedure emp_ins(emp_row emp%rowtype) as
pragma autonomous_transaction;
begin
insert into temp_type(empno,ename) values(emp_row.empno,emp_row.ename);
commit;
end;
create or replace trigger emp_ins_trig before insert on emp for each row
declare
/* empr emp_types.emprowtype%type;*/
empr emp%rowtype;
begin
empr.empno := :new.empno;
empr.ename := :new.ename;
emp_ins(empr);
end;
/unfortunately , in oracle we dont have a facility to access the members of a record or recordset by their position
Such facility is very much there in Visual Basic , similar programming tools.
we can access the members of a recordset by the index position ( here index means the position of the field) -
Store all values from updateable report on clientside for later use
apex 4.2 , 11xe
hello,
it is possible to store all values from an updateable report to something like an cache BEFORE sent it to DB ?
Background:
i have an modified updateable report ,look the jpg
http://www10.pic-upload.de/25.06.13/3zq5wr23awwg.jpg
updateable report have ever 29 rows. as example i make time entrys for an employee. very often the next employee have the same timeentrys. now iam thinking about to make the entrys for the first employee, then click a button to store the values from ALL cells into somting like a javascript cache or jquery.data() . when i pull another employee from lov i have a fresh empty report( with 29 rows) and now i want to call the data back from cache to the cells (with another button). the cache shouldnt be destroyed when refresh the page,cause there is a page refresh when pull another employee from lov.
is it possible to store all cell values(empty or not) from report all in one?
what is the best and simplest way ?
good would be an example for the code or method i should use.
or is somthing inside apex i could use for that. i looked in apex.api but didnt found something.
my report based on a view with iof trigger and apex collection.
greets/christianthx for answer jarola and sorry for my bad english.
apex collection will not work.
let me explain why not and i think something like javascript/jquery is better for that.
there is a table MAZEIT and i have this updateable report. when i select an employee from lov, a collection will be created. the collection look in MAZEIT ,perhaps there are real timeentrys, in this case the collection will be modified and give me 29 rows,some are filled. or there are no real entrys and the collection give me 29 empty rows.
here my report sql:
select
"HID_SEQ_ID",
"DATUM",
"WOTAG",
"WOTAGNR",
"KNDABT_ID",
"ZEIT",
"BEGINN",
"ENDE",
"PAUSE",
"ZUSCHLAG",
"BEM",
"MELDUNG"
from "#OWNER#"."V_COLL_MAZEIT"
here the v_coll_mazeit (view) sql
CREATE OR REPLACE VIEW V_COLL_MAZEIT AS
SELECT seq_id HID_SEQ_ID -- APEX_COLLECTIONS.SEQ_ID
,C001 HID_MAZEIT_ID -- MAZEIT.ID
,C002 DATUM -- Datum DD.MM.YYYY
,C003 WOTAG -- Wochentag Mo/Di/...
,C004 WOTAGNR -- Wochentag 1/2/...
,C005 KNDABT_ID -- Abteilung
,C006 ZEIT -- Zeit in HH24:MI
,C007 BEGINN -- Beginn in HH24:MI
,C008 ENDE -- Ende in HH24:MI
,C009 PAUSE -- Pause in HH24:MI
,C010 ZUSCHLAG
,C011 BEM
,C040 HID_MANDANT_ID
,C041 HID_KND_ID
,C042 HID_MA_ID
,C043 HID_KW
,C048 HID_HASH4CHECK -- Hash für Check auf Änderungen MAZEIT
,C049 HID_SORTIER -- für ORDER BY hier Arbeitsbeginn
,C050 MELDUNG -- für FehlerMeldungen
FROM APEX_COLLECTIONS
WHERE COLLECTION_NAME='V_COLL_MAZEIT'
ORDER BY HID_SORTIER;
here the trigger (iof) from v_coll_mazeit
CREATE OR REPLACE TRIGGER "V_COLL_MAZEIT_IOF_U_TRG"
INSTEAD OF UPDATE ON V_COLL_MAZEIT
FOR EACH ROW
BEGIN
--RAISE_APPLICATION_ERROR(-20004,'NIX DA');
CM_MEAT.V_COLL_MAZEIT_IOF_U_TRG(
:NEW.HID_SEQ_ID
,:NEW.HID_MAZEIT_ID
,:NEW.DATUM
,:NEW.WOTAG
,:NEW.WOTAGNR
,:NEW.KNDABT_ID
,:NEW.ZEIT
,:NEW.BEGINN
,:NEW.ENDE
,:NEW.PAUSE
,:NEW.ZUSCHLAG
,:NEW.BEM
,:NEW.HID_HASH4CHECK
,:NEW.HID_SORTIER
,:NEW.MELDUNG
END V_COLL_MAZEIT_IOF_U_TRG;
and here a package procedure when i select an employee:
PROCEDURE V_COLL_MAZEIT_PROC(
iAction IN PLS_INTEGER,
iDatum IN DATE DEFAULT SYSDATE,
iMandantId IN MAZEIT.MANDANT_ID%TYPE,
iKndId IN MAZEIT.KND_ID%TYPE,
iMaId IN MAZEIT.MA_ID%TYPE,
oCollName OUT VARCHAR2)
IS
TK_FUNC_NAME CONSTANT USER_OBJECTS.OBJECT_NAME%TYPE := 'V_COLL_MAZEIT_PROC';
TK_COLL_NAME CONSTANT APEX_COLLECTIONS.COLLECTION_NAME%TYPE := 'V_COLL_MAZEIT';
TK_MD5 CONSTANT VARCHAR2(2) := 'NO';
TYPE t_Tage_TAB IS TABLE OF DATE INDEX BY BINARY_INTEGER;
TYPE t_TageVC_TAB IS TABLE OF VARCHAR2(8) INDEX BY BINARY_INTEGER;
TYPE t_TageI_TAB IS TABLE OF PLS_INTEGER INDEX BY BINARY_INTEGER;
tTage t_Tage_TAB;
tTageVC t_TageVC_TAB;
tTageI t_TageI_TAB;
vDatum DATE;
vDatumCh VARCHAR2(8);
vKW4Db MAZEIT.KW%TYPE;
vI PLS_INTEGER := 0;
vAnz PLS_INTEGER := 0;
BEGIN
FOR rec IN (SELECT * FROM NLS_SESSION_PARAMETERS)
LOOP
InsProto(rec.PARAMETER||'=['||rec.VALUE||']',
QK_PACK_NAME,TK_FUNC_NAME);
END LOOP;
CMT.InsProto('iAction='||iAction||', iDatum='||iDatum||', iMandantId='||iMandantId||', iKndId='||iKndId||', iMaId'||iMaId,
QK_PACK_NAME,TK_FUNC_NAME);
oCollName := TK_COLL_NAME;
IF iAction=0 THEN -- löschen
IF APEX_COLLECTION.COLLECTION_EXISTS(p_collection_name=>TK_COLL_NAME) THEN
APEX_COLLECTION.TRUNCATE_COLLECTION(TK_COLL_NAME);
APEX_COLLECTION.DELETE_COLLECTION(TK_COLL_NAME);
END IF;
|| Säubern und anlegen
ELSIF iAction=1 THEN
IF APEX_COLLECTION.COLLECTION_EXISTS(p_collection_name=>TK_COLL_NAME) THEN
APEX_COLLECTION.TRUNCATE_COLLECTION(p_collection_name=>TK_COLL_NAME);
ELSE
APEX_COLLECTION.CREATE_COLLECTION(p_collection_name=>TK_COLL_NAME);
END IF;
vDatum := NVL(iDATUM,SYSDATE);
vDatum := TO_DATE(TO_CHAR(vDatum,'YYYYMMDD')||'000000','YYYYMMDDHH24MISS');
vKW4Db := GetKW4Db(vDatum);
tTage(1) := CMT.GetMonday(vDATUM,0);
SELECT tTage(1) + 1DAY,tTage(1) + 2DAY,tTage(1) + 3DAY,tTage(1) + 4DAY,tTage(1) + 5DAY,tTage(1) + 6DAY
INTO tTage(2),tTage(3),tTage(4),tTage(5),tTage(6),tTage(7)
FROM DUAL;
FOR i IN 1..7 LOOP tTageI(i) := 0; tTageVC(i) := TO_CHAR(tTage(i),'YYYYMMDD'); END LOOP;
-- erste Zeile enthält Default-Werte
APEX_COLLECTION.add_member( p_COLLECTION_name=> TK_COLL_NAME,p_generate_md5=>TK_MD5
,P_C001 => 0 -- MAZEIT.ID
,P_C002 => '<b>Vorgabe</b>' -- Datum DD.MM.YYYY
,P_C003 => ' ' -- Wochentag Mo/Di/...
,P_C004 => ' ' -- Wochentag 1/2/...
,P_C005 => 0 -- MAZEIT.KNDABT_ID
,P_C006 => NULL -- Zeit in HH24:MI
,P_C007 => NULL -- Beginn in HH24:MI
,P_C008 => NULL -- Ende in HH24:MI
,P_C009 => NULL -- Pause in HH24:MI
,P_C010 => NULL -- Zuschlag
,P_C011 => NULL -- Bem
,P_C040 => iMandantId
,P_C041 => iKndId
,P_C042 => iMaId
,P_C043 => vKW4Db
,P_C048 => '-1' -- Hash für Check auf Änderungen MAZEIT
,P_C049 => ' ' -- für ORDER BY hier Arbeitsbeginn
,P_C050 => NULL
FOR rec IN (SELECT z.*,
TO_CHAR(DBMS_UTILITY.get_hash_value(
z.id||'|'||
z.mandant_id||'|'||
z.majob_id||'|'||
z.ma_id||'|'||
z.knd_id||'|'||
z.kndabt_id||'|'||
z.kw||'|'||
z.arb_beg||'|'||
z.arb_end||'|'||
z.zeit||'|'||
z.pause||'|'||
z.zuschlag||'|'||
z.stk_anz||'|'||
z.stk_kg||'|'||
z.stk_gemuur||'|'||
z.stk_bezahlt||'|'||
z.bem||'|'||
z.ART4RECH
,1,POWER(2,30))) AS HID_HASH4CHECK
FROM MAZEIT z
WHERE z.MANDANT_ID=iMandantId AND
z.KND_ID=iKndId AND
z.MA_ID=iMaId AND
z.KW = GetKW4Db(tTage(1)) AND
z.ART4RECH IN (CMT.GetTCVNum('MAZEIT_ART4RECH_STD'),CMT.GetTCVNum('MAZEIT_ART4RECH_STK'),CMT.GetTCVNum('MAZEIT_ART4RECH_KG'))
ORDER BY z.ARB_BEG)
LOOP
IF rec.ZUSCHLAG=0 THEN
rec.ZUSCHLAG := NULL;
END IF;
vI := 0;
vDatumCh := TO_CHAR(rec.ARB_BEG,'YYYYMMDD');
FOR i IN 1..7 LOOP
IF tTageVC(i)=vDatumCh THEN
tTageI(i) := tTageI(i) + 1;
vI := i;
EXIT;
END IF;
END LOOP;
-- Stücklohn kommt an den Anfang der Bemerkung gekennzeichnet mit QK_COLL_MAZEIT_STK_KZ ursprüngliche Bemekuung nach dem :
rec.BEM := RTRIM(rec.BEM);
IF rec.ART4RECH = CMT.GetTCVNum('MAZEIT_ART4RECH_STK') THEN
DECLARE
vBem MAZEIT.BEM%TYPE := QK_COLL_MAZEIT_STK_KZ;
BEGIN
IF rec.STK_BEZAHLT > 0. THEN
vBem := QK_COLL_MAZEIT_STK_KZ||TO_CHAR(rec.stk_bezahlt,'FM9999D00');
ELSIF rec.STK_ANZ > 0 THEN
vBem := QK_COLL_MAZEIT_STA_KZ||TO_CHAR(rec.stk_anz,'FM9999');
END IF;
IF rec.BEM IS NULL THEN
rec.BEM := vBem;
ELSE
rec.BEM := SUBSTR(vBem||':'||rec.BEM,1,CMT.GetColLen('MAZEIT','BEM'));
END IF;
END;
ELSIF rec.ART4RECH = CMT.GetTCVNum('MAZEIT_ART4RECH_KG') THEN
DECLARE
vBem MAZEIT.BEM%TYPE := QK_COLL_MAZEIT_KG_KZ;
BEGIN
IF rec.STK_KG > 0. THEN
vBem := QK_COLL_MAZEIT_KG_KZ||TO_CHAR(rec.stk_kg,'FM999999D000');
END IF;
IF rec.BEM IS NULL THEN
rec.BEM := vBem;
ELSE
rec.BEM := SUBSTR(vBem||':'||rec.BEM,1,CMT.GetColLen('MAZEIT','BEM'));
END IF;
END;
END IF;
IF vI>0 THEN
IF tTageI(vI)=1 THEN
APEX_COLLECTION.add_member( p_COLLECTION_name=> TK_COLL_NAME,p_generate_md5=>TK_MD5
,P_C001 => rec.id -- MAZEIT.ID
,P_C002 => TO_CHAR(rec.ARB_BEG,'DD.MM.YYYY') -- Datum DD.MM.YYYY
,P_C003 => CMT.WoTag(rec.ARB_BEG) -- Wochentag Mo/Di/...
,P_C004 => CMT.WoTagNr(rec.ARB_BEG) -- Wochentag 1/2/...
,P_C005 => rec.KNDABT_ID -- MAZEIT.KNDABT_ID
,P_C006 => CMT.Minuten2InduZeit(rec.ZEIT) -- Zeit als InduZeit in HH24,MI
,P_C007 => TO_CHAR(rec.ARB_BEG,'HH24:MI') -- Beginn in HH24:MI
,P_C008 => TO_CHAR(rec.ARB_END,'HH24:MI') -- Ende in HH24:MI
,P_C009 => CMT.Minuten2HHMI(rec.PAUSE,TRUE) -- Pause in HH24:MI
,P_C010 => rec.ZUSCHLAG
,P_C011 => rec.BEM
,P_C040 => iMandantId
,P_C041 => iKndId
,P_C042 => iMaId
,P_C043 => vKW4Db
,P_C048 => rec.HID_HASH4CHECK -- Hash für Check auf Änderungen MAZEIT
,P_C049 => TO_CHAR(rec.ARB_BEG,'YYYYMMDDHH24MI') -- für ORDER BY hier Arbeitsbeginn
,P_C050 => NULL -- für FehlerMeldungen
ELSE
APEX_COLLECTION.add_member( p_COLLECTION_name=> TK_COLL_NAME,p_generate_md5=>TK_MD5
,P_C001 => rec.id -- MAZEIT.ID
,P_C002 => NULL -- Datum DD.MM.YYYY
,P_C003 => NULL -- Wochentag Mo/Di/...
,P_C004 => NULL -- Wochentag 1/2/...
,P_C005 => rec.KNDABT_ID -- MAZEIT.KNDABT_ID
,P_C006 => CMT.Minuten2InduZeit(rec.ZEIT) -- Zeit als InduZeit in HH24,MI
,P_C007 => TO_CHAR(rec.ARB_BEG,'HH24:MI') -- Beginn in HH24:MI
,P_C008 => TO_CHAR(rec.ARB_END,'HH24:MI') -- Ende in HH24:MI
,P_C009 => CMT.Minuten2HHMI(rec.PAUSE,TRUE) -- Pause in HH24:MI
,P_C010 => rec.ZUSCHLAG
,P_C011 => rec.BEM
,P_C040 => iMandantId
,P_C041 => iKndId
,P_C042 => iMaId
,P_C043 => vKW4Db
,P_C048 => rec.HID_HASH4CHECK -- Hash für Check auf Änderungen MAZEIT
,P_C049 => TO_CHAR(rec.ARB_BEG,'YYYYMMDDHH24MI') -- für ORDER BY hier Arbeitsbeginn
,P_C050 => NULL -- für FehlerMeldungen
END IF;
vAnz := vAnz + 1;
END IF;
END LOOP;
FOR i IN 1..7 LOOP
IF tTageI(i)<4 THEN
FOR j IN tTageI(i)+1..4 LOOP
IF j=1 THEN
APEX_COLLECTION.add_member( p_COLLECTION_name=> TK_COLL_NAME,p_generate_md5=>TK_MD5
,P_C001 => -1 -- MAZEIT.ID
,P_C002 => TO_CHAR(tTage(i),'DD.MM.YYYY') -- Datum DD.MM.YYYY
,P_C003 => CMT.WoTag(tTage(i)) -- Wochentag Mo/Di/...
,P_C004 => CMT.WoTagNr(tTage(i)) -- Wochentag 1/2/...
,P_C005 => 0 -- MAZEIT.KNDABT_ID
--,P_C006 => Minuten2InduZeit(0) -- Zeit als InduZeit in HH24,MI
,P_C006 => NULL -- Zeit als InduZeit in HH24,MI
--,P_C007 => '06:30' -- Beginn in HH24:MI
,P_C007 => NULL -- Beginn in HH24:MI
,P_C008 => NULL -- Ende in HH24:MI
--,P_C009 => Minuten2HHMI(0) -- Pause in HH24:MI
,P_C009 => NULL -- Pause in HH24:MI
,P_C010 => NULL -- Zuschlag
,P_C011 => NULL -- Bem
,P_C040 => iMandantId
,P_C041 => iKndId
,P_C042 => iMaId
,P_C043 => vKW4Db
,P_C048 => '-1' -- Hash für Check auf Änderungen MAZEIT
,P_C049 => TO_CHAR(tTage(i),'YYYYMMDD')||'99'||TO_CHAR(j,'FM09') -- für ORDER BY hier Arbeitsbeginn
,P_C050 => NULL
ELSE -- auffüllen
APEX_COLLECTION.add_member( p_COLLECTION_name=> TK_COLL_NAME,p_generate_md5=>TK_MD5
,P_C001 => -1 -- MAZEIT.ID
,P_C002 => NULL -- Datum DD.MM.YYYY
,P_C003 => NULL -- Wochentag Mo/Di/...
,P_C004 => NULL -- Wochentag 1/2/...
,P_C005 => 0 -- MAZEIT.KNDABT_ID
--,P_C006 => Minuten2HHMI(0) -- Zeit in HH24:MI
,P_C006 => NULL -- Zeit in HH24:MI
--,P_C007 => '06:30' -- Beginn in HH24:MI
,P_C007 => NULL -- Beginn in HH24:MI
,P_C008 => NULL -- Ende in HH24:MI
--,P_C009 => Minuten2InduZeit(0) -- Pause als InduZeit in HH24,MI
,P_C009 => NULL -- Pause als InduZeit in HH24,MI
,P_C010 => NULL -- Zuschlag
,P_C011 => NULL -- Bem
,P_C040 => iMandantId
,P_C041 => iKndId
,P_C042 => iMaId
,P_C043 => vKW4Db
,P_C048 => '-1' -- Hash für Check auf Änderungen MAZEIT
,P_C049 => TO_CHAR(tTage(i),'YYYYMMDD')||'99'||TO_CHAR(j,'FM09') -- für ORDER BY hier Arbeitsbeginn
,P_C050 => NULL
END IF;
END LOOP;
END IF;
END LOOP;
vI := 0;
FOR rec IN (SELECT * FROM V_COLL_MAZEIT) LOOP
vI := vI + 1;
CMT.InsProto('i='||LPAD(TO_CHAR(vI),3,' ')||':'||
rec.hid_seq_id||'|'||
rec.hid_mazeit_id||'|'||
rec.datum||'|'||
rec.wotag||'|'||
rec.wotagnr||'|'||
rec.zeit||'|'||
rec.beginn||'|'||
rec.ende||'|'||
rec.pause||'|'||
rec.zuschlag||'|'||
rec.bem||'|'||
rec.hid_hash4check||'|'||
rec.hid_sortier||'|'||
rec.meldung
,QK_PACK_NAME,TK_FUNC_NAME);
END LOOP;
ELSE
raise_Application_ERROR(-20100,'kann ich doch nicht Action='||TO_CHAR(iAction));
END IF;
END V_COLL_MAZEIT_PROC;
and here the procedure (look for real entrys in table)
PROCEDURE V_COLL_MAZEIT_IOF_U_TRG(
iHID_SEQ_ID apex_collections.seq_id%TYPE
,iHID_MAZEIT_ID apex_collections.C001%TYPE
,iDATUM apex_collections.C002%TYPE
,iWOTAG apex_collections.C003%TYPE
,iWOTAGNR apex_collections.C004%TYPE
,iKNDABT_ID apex_collections.C005%TYPE
,iZEIT apex_collections.C006%TYPE
,iBEGINN apex_collections.C007%TYPE
,iENDE apex_collections.C008%TYPE
,iPAUSE apex_collections.C009%TYPE
,iZUSCHLAG apex_collections.C010%TYPE
,iBEM apex_collections.C011%TYPE
,iHID_HASH4CHECK apex_collections.C048%TYPE
,iHID_SORTIER apex_collections.C049%TYPE
,iMELDUNG apex_collections.C050%TYPE
IS
PRAGMA AUTONOMOUS_TRANSACTION;
TK_FUNC_NAME CONSTANT USER_OBJECTS.OBJECT_NAME%TYPE := 'V_COLL_MAZEIT_IOF_U_TRG';
TK_COLL_NAME CONSTANT APEX_COLLECTIONS.COLLECTION_NAME%TYPE := 'V_COLL_MAZEIT';
vRcString VARCHAR2(2000) := NULL;
rCollMaZeit0 V_COLL_MAZEIT%ROWTYPE;
rCollMaZeit V_COLL_MAZEIT%ROWTYPE;
rMaZeit MAZEIT%ROWTYPE;
vHash4Check PLS_INTEGER;
vURow ROWID;
BEGIN
CMT.InsProto(
ihid_seq_id||'|'||
ihid_mazeit_id||'|'||
idatum||'|'||
iwotag||'|'||
iwotagnr||'|'||
iKNDABT_ID||'|'||
izeit||'|'||
ibeginn||'|'||
iende||'|'||
ipause||'|'||
izuschlag||'|'||
ibem||'|'||
ihid_hash4check||'|'||
ihid_sortier||'|'||
imeldung
,QK_PACK_NAME,TK_FUNC_NAME);
-- VIEW-ZeitZeile lesen
SELECT t.* INTO rCollMaZeit
FROM V_COLL_MAZEIT t
WHERE t.HID_SEQ_ID = iHID_SEQ_ID;
IF iHID_MAZEIT_ID!=rCollMaZeit.HID_MAZEIT_ID OR
iHID_HASH4CHECK!=rCollMaZeit.HID_HASH4CHECK THEN
vRcString := 'Daten seit Anzeige verändert';
GOTO MARK_TRANSEND;
END IF;
-- VIEW-ZeitDefaultZeile setzen
IF rCollMaZeit.HID_MAZEIT_ID=0 THEN
--,P_C005 => 0 -- MAZEIT.KNDABT_ID
--,P_C006 => NULL -- Zeit in HH24,MI
--,P_C007 => NULL -- Beginn in HH24:MI
--,P_C008 => NULL -- Ende in HH24:MI
--,P_C009 => NULL -- Pause in HH24,MI
--,P_C010 => NULL -- Zuschlag
--,P_C011 => NULL -- Bem
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>5, p_attr_value=>iKNDABT_ID);
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>6, p_attr_value=>iZEIT);
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>7, p_attr_value=>iBEGINN);
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>8, p_attr_value=>iENDE);
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>9, p_attr_value=>iPAUSE);
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>10, p_attr_value=>iZUSCHLAG);
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>11, p_attr_value=>iBEM);
IF iBEM LIKE '#%' THEN -- Verteilen
-- VIEW-ZeitDefaultZeile lesen
SELECT t.* INTO rCollMaZeit0
FROM V_COLL_MAZEIT t
WHERE t.HID_MAZEIT_ID = 0;
rCollMaZeit0.BEM := SUBSTR(iBEM,2);
DECLARE
vAnz PLS_INTEGER := 0;
nVert MAZEIT.ZEIT%TYPE;
nZeitMinuten MAZEIT.ZEIT%TYPE;
nDiffMinuten MAZEIT.ZEIT%TYPE;
BEGIN
SELECT NVL(COUNT(*),0) INTO vAnz
FROM V_COLL_MAZEIT t
WHERE t.HID_MAZEIT_ID = -1 AND
t.DATUM IS NOT NULL AND
t.WOTAGNR IN ('1','2','3','4','5'); -- nur Mo-Fr
IF vAnz<=0 THEN
vRcString := 'Verteilen nicht möglich keine freien Tage gefunden';
ELSIF TRIM(iZEIT) IS NULL OR TRIM(iZEIT) IN ('00,00','0,00','0',',00',',0','0,','0,0') THEN
vRcString := 'Verteilen von Null Minuten nicht möglich';
ELSE
nDiffMinuten := 0;
nZeitMinuten := CMT.InduZeit2MinutenNum(TRIM(iZEIT));
IF nZeitMinuten>(vAnz*1440) THEN
vRcString := 'Zu verteilende Zeit zu groß';
ELSIF vAnz>1 THEN
nVert := FLOOR(nZeitMinuten/vAnz);
nDiffMinuten := nZeitMinuten - (nVert*vAnz);
nZeitMinuten := nVert;
END IF;
IF vRcString IS NULL THEN
FOR rec IN (SELECT t.* INTO rCollMaZeit
FROM V_COLL_MAZEIT t
WHERE t.HID_MAZEIT_ID = -1 AND
t.DATUM IS NOT NULL AND
t.WOTAGNR IN ('1','2','3','4','5')) -- nur Mo-Fr)
LOOP
rCollMaZeit := rec;
vRcString := qV_COLL_MAZEIT_Insert(iKNDABT_ID, iZEIT, nZeitMinuten+nDiffMinuten, iBEGINN, iENDE, iPAUSE, iZUSCHLAG, SUBSTR(iBEM,2),
rCollMaZeit0, rCollMaZeit, rMaZeit);
IF vRcString IS NOT NULL THEN
EXIT;
END IF;
nDiffMinuten := 0;
END LOOP;
END IF;
END IF;
END;
END IF;
-- MAZEIT-Vorhandener Eintrag
ELSIF rCollMaZeit.HID_MAZEIT_ID>0 THEN
SELECT z.ROWID, TO_CHAR(DBMS_UTILITY.get_hash_value(
z.id||'|'||
z.mandant_id||'|'||
z.majob_id||'|'||
z.ma_id||'|'||
z.knd_id||'|'||
z.kndabt_id||'|'||
z.kw||'|'||
z.arb_beg||'|'||
z.arb_end||'|'||
z.zeit||'|'||
z.pause||'|'||
z.zuschlag||'|'||
z.stk_anz||'|'||
z.stk_kg||'|'||
z.stk_gemuur||'|'||
z.stk_bezahlt||'|'||
z.bem||'|'||
z.ART4RECH
,1,POWER(2,30))) AS HID_HASH4CHECK
INTO vURow, vHash4Check
FROM MAZEIT z
WHERE z.ID=rCollMaZeit.HID_MAZEIT_ID
FOR UPDATE NOWAIT;
IF vHash4Check!=rCollMaZeit.HID_HASH4CHECK THEN
vRcString := 'Daten seit Anzeige verändert';
GOTO MARK_TRANSEND;
END IF;
SELECT z.* INTO rMaZeit
FROM MAZEIT z
WHERE ROWID=vURow;
rMaZeit.KNDABT_ID := TO_NUMBER(TRIM(iKNDABT_ID));
IF TRIM(iBEGINN) IS NULL THEN
rMaZeit.ARB_BEG := NULL;
ELSE
rMaZeit.ARB_BEG := TO_DATE(TO_CHAR(rMaZeit.ARB_BEG,'YYYYMMDD')||TRIM(SUBSTR(iBEGINN,1,5)),'YYYYMMDDHH24:MI');
END IF;
IF TRIM(iENDE) IS NULL THEN
rMaZeit.ARB_END := NULL;
ELSE
rMaZeit.ARB_END := TO_DATE(TO_CHAR(rMaZeit.ARB_BEG,'YYYYMMDD')||TRIM(SUBSTR(iENDE,1,5)),'YYYYMMDDHH24:MI');
END IF;
IF TRIM(iZEIT) IS NULL THEN
rMaZeit.ZEIT := NULL;
ELSE
rMaZeit.ZEIT := CMT.InduZeit2MinutenNum(TRIM(iZEIT));
END IF;
IF TRIM(iPAUSE) IS NULL THEN
rMaZeit.PAUSE := NULL;
ELSE
rMaZeit.PAUSE := CMT.HHMI2Minuten(TRIM(iPAUSE));
END IF;
IF iWOTAGNR IN (6,7) AND
rMaZeit.PAUSE IS NOT NULL AND rMaZeit.PAUSE<>0 THEN
vRcString := 'Eintrag Pause am Wochenende nicht erlaubt';
GOTO MARK_TRANSEND;
END IF;
IF TRIM(iZUSCHLAG) IS NULL THEN
rMaZeit.ZUSCHLAG := NULL;
ELSE
rMaZeit.ZUSCHLAG := TO_NUMBER(TRIM(iZUSCHLAG));
END IF;
IF RTRIM(iBEM) IS NULL THEN
rMaZeit.BEM := NULL;
ELSE
rMaZeit.BEM := RTRIM(iBEM);
END IF;
IF (rMaZeit.KNDABT_ID IS NOT NULL AND rMaZeit.KNDABT_ID>0) OR
rMaZeit.ARB_BEG IS NOT NULL OR rMaZeit.ARB_END IS NOT NULL OR
(rMaZeit.ZEIT IS NOT NULL AND rMaZeit.ZEIT!=0) OR rMaZeit.PAUSE IS NOT NULL OR
rMaZeit.ZUSCHLAG IS NOT NULL OR rMaZeit.BEM IS NOT NULL THEN
DECLARE
vBem MAZEIT.BEM%TYPE := rMaZeit.BEM;
BEGIN
rMaZeit.ZUSCHLAG := NVL(rMaZeit.ZUSCHLAG,0.0);
qV_COLL_MAZEIT_BEM_CHK(rMaZeit); -- Bem prüfen wg. ART4RECH Verschlüsselung mittels QK_COLL_MAZEIT_STK_KZ
UPDATE MAZEIT z
SET z.KNDABT_ID = rMaZeit.KNDABT_ID
,z.ARB_BEG = rMaZeit.ARB_BEG
,z.ARB_END = rMaZeit.ARB_END
,z.ZEIT = rMaZeit.ZEIT
,z.PAUSE = rMaZeit.PAUSE
,z.ZUSCHLAG = rMaZeit.ZUSCHLAG
,z.BEM = rMaZeit.BEM
,z.STK_BEZAHLT = rMaZeit.STK_BEZAHLT
,z.STK_ANZ = rMaZeit.STK_ANZ
,z.STK_KG = rMaZeit.STK_KG
,z.ART4RECH = rMaZeit.ART4RECH
WHERE ROWID=vURow;
IF SQL%ROWCOUNT=1 THEN
NULL;
ELSIF SQL%ROWCOUNT<1 THEN
RAISE NO_DATA_FOUND;
ELSE
RAISE TOO_MANY_ROWS;
END IF;
rMaZeit.BEM := vBem;
END;
ELSE
DELETE FROM MAZEIT z
WHERE ROWID=vURow;
IF SQL%ROWCOUNT=1 THEN
NULL;
ELSIF SQL%ROWCOUNT<1 THEN
RAISE NO_DATA_FOUND;
ELSE
RAISE TOO_MANY_ROWS;
END IF;
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>1, p_attr_value=>-1);
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>48, p_attr_value=>'-1');
END IF;
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>5, p_attr_value=>rMaZeit.KNDABT_ID);
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>6, p_attr_value=>CMT.Minuten2InduZeit(rMaZeit.ZEIT));
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>7, p_attr_value=>TO_CHAR(rMaZeit.ARB_BEG,'HH24:MI'));
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>8, p_attr_value=>TO_CHAR(rMaZeit.ARB_END,'HH24:MI'));
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>9, p_attr_value=>CMT.Minuten2InduZeit(rMaZeit.PAUSE,TRUE) );
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>10, p_attr_value=>rMaZeit.ZUSCHLAG);
APEX_COLLECTION.update_member_attribute( p_COLLECTION_name=> TK_COLL_NAME, p_seq=>rCollMaZeit.HID_SEQ_ID
,p_attr_number=>11, p_attr_value=>RTRIM(rMaZeit.BEM));
-- MAZEIT neuer Eintrag
ELSIF rCollMaZeit.HID_MAZEIT_ID=-1 THEN
-- VIEW-ZeitDefaultZeile lesen
SELECT t.* INTO rCollMaZeit0
FROM V_COLL_MAZEIT t
WHERE t.HID_MAZEIT_ID = 0;
vRcString := qV_COLL_MAZEIT_Insert(iKNDABT_ID, iZEIT, NULL, iBEGINN, iENDE, iPAUSE, iZUSCHLAG, iBEM,
rCollMaZeit0, rCollMaZeit, rMaZeit);
ELSE
vRcString := 'Ungültige HID_MAZEIT_ID '||TO_CHAR(rCollMaZeit.HID_MAZEIT_ID);
END IF;
<<MARK_TRANSEND>>
IF vRcString IS NULL THEN
COMMIT;
ELSE
ROLLBACK;
RAISE_APPLICATION_ERROR(-20100,vRcString);
END IF;
END V_COLL_MAZEIT_IOF_U_TRG;
and in end there are 3 other procedures, all for table MAZEIT, the collection and and the report.
in princip its a good idea,to create another collection, but difficult to bind it to the report TOO,cause my "cell-fill- functionality" is to complicated.
my idea is another: to look with javascript/jquery whatever on clientside the cell-values. and only the editable cells. not the hidden cells.there would be ca. 180 editable cells. i want store the values from this cells all in one in a cache (clientside! ).
then select next employee (collection will be created with view ect.) and give me this 29 rows. in this moment i have cells with ID f02_0001 as example and can use the cache values with that. the ID's ever the same,cause i have ever 29 rows.
greets/christian
Maybe you are looking for
-
Safari 5.0.6 can't "see" Flash Plug-In
I'm running 10.5.8 on my MacBook. For a while I have been having problems with the Flash player plug-in. I use the BBC News and iPlayer sites a lot so this is a big problem as they rely almost totally on Flash. The pattern was that having been workin
-
I cannot send or receive emails. The message I receive is: The connection to the server "imap.aol.com" on port 993 timed out. How do I rectify this situation? Thanks
-
Java Development Role problems!
I have tried to add the java development role to a users account. I have added the following roles: SAP_JAVA_NWADMIN_CENTRAL SAP_JAVA_NWADMIN_LOCAL Apparently they are meant to get a new tab but it does not appear. Am I adding the right roles?
-
Mobile phone not being recognised via USB port
A few days ago I plugged my Motorola V3x phone into a USB port to download some pictures and was presented with some Windows to fill out some information. As I could not complete the operation at that time I closed the windows to retry at a later dat
-
This is my problem. Why doesnt it work with a new id but only for the old ones?!?