DML statements in Function
Hi,
I have small question
Why we should not written DML statements in Function ?
Can any one explain that
Thanks...
971822 wrote:
Hi,
I have small question
Why we should not written DML statements in Function ?
Can any one explain thatThe answer is: "it depends".
Functions are used for many many different purposes, and it is the purpose that determines whether it's a good idea to write DML statements in a function.
As already mentioned, there are the purity rules, that basically say "if you're going to be calling the function from queries etc. then it cannot do DML, otherwise you'll get an exception"
But there are also functions that are intended to be used within PL/SQL code for other purposes. It may be that you need something that updates some data and returns a result from that updated data, or it returns how much data was effected, in which case it's perfectly ok to have a function do some DML.
As long as the code is well modularised and makes sense for the purpose for which it is intended, then you are doing the right thing. Where it goes wrong is when people lack design in their applications, and try to write 'generic' functions to be used in PL/SQL or SQL, or fail to modularise code so a function is doing the task of several things based on some parameters etc. when really each task should seperated to it's own functions/procedures etc.
So we cannot just say that we "should not" write DML inside functions; but we can say that there are design considerations (or lack of) when it would be bad practice to do so.
Similar Messages
-
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. -
can we select udf which contains dml statements?
1007109 wrote:
can we select udf which contains dml statements?
Excellent question! And one that illustrates just how careful you have to be when you ASK questions or provide answers.
As with many things Oracle the correct answer is: it depends.
Yes - you can. And no - you can't. And also, yes - you can!
ANY one of those answers is correct, depending on what assumptions the questioner is making and/or what assumptions that you, the answerer are making.
Sometimes a interviewer will ask this old 'trick' question and then get mad at you if you don't give them the answer that they want even if you give them an answer that is CORRECT and even if you explain WHY your answer is correct.
Some questioners are looking for the answer that Frank gave:
>
A function that performs DML (or that calls another sub-program that performs DML) can NOT be used in a SQL statement, such as SELECT.
>
If you just read the 'restrictions' section in the Advanced App Developer's guide you might come up with the answer that Frank gave.
http://docs.oracle.com/cd/E11882_01/appdev.112/e25518/adfns_packages.htm#i1008107
>
Restrictions
When a new SQL statement is run, checks are made to see if it is logically embedded within the execution of a running SQL statement. This occurs if the statement is run from a trigger or from a subprogram that was in turn invoked from the running SQL statement. In these cases, further checks determine if the new SQL statement is safe in the specific context.
These restrictions are enforced on subprograms:
A subprogram invoked from a query (SELECT statement) or DML statement cannot end the current transaction, create or rollback to a savepoint, or ALTER the system or session.
A subprogram invoked from a query or parallelized DML statement cannot run a DML statement or otherwise modify the database.
A subprogram invoked from a DML statement cannot read or modify the particular table being modified by that DML statement.
>
But then if you read the very next sentence in that doc you will see this:
>
You can avoid these restrictions if the execution of the new SQL statement is not logically embedded in the context of the running statement. PL/SQL autonomous transactions provide one escape (see "Autonomous Transactions" ).
>
And finally if the term DML includes the SELECT statement and the SQL Language doc DOES use it that way
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_1001.htm#i2099257
>
The SELECT statement is a limited form of DML statement in that it can only access data in the database. It cannot manipulate data stored in the database, although it can manipulate the accessed data before returning the results of the query.
>
That doc also lists statements other than the traditional SELECT, INSERT, UPDATE or DELETE
>
Data Manipulation Language (DML) Statements
Data manipulation language (DML) statements access and manipulate data in existing schema objects. These statements do not implicitly commit the current transaction. The data manipulation language statements are:
CALL
DELETE
EXPLAIN PLAN
INSERT
LOCK TABLE
MERGE
SELECT
UPDATE
>
So the CORRECT answer is:
1. No, Frank's answer, if by DML you are only considering INSERT, UPDATE or DELETE statements and you do NOT use the AUTONOMOUS_TRANSACTION pragma.
2. Yes - if DML includes SELECT (LOCK TABLE also works) - you don't need the pragma. A common use of functions is in LOOKUP operations. These functions can be, but should NOT be, called from a sql statement.
3. Yes - if the AUTONOMOUS_TRANSACTION pragma is used. This is NOT recommended.
Try some of the following code examples
>
create or replace function get_dname(p_deptno IN number) return varchar2 is
v_dname dept.dname%type;
begin
select dname into v_dname from dept where deptno = p_deptno;
return v_dname;
end;
select empno, ename, deptno, get_dname(deptno) from emp e
where rownum < 4
EMPNO,ENAME,DEPTNO,GET_DNAME(DEPTNO)
7369,SMITH,20,RESEARCH*
7499,ALLEN,30,SALES**
7521,WARD,30,SALES**
create or replace function get_dname1(p_deptno IN number) return varchar2 is
v_dname dept.dname%type;
begin
update dept set dname = dname || '*' where deptno = p_deptno;
select dname into v_dname from dept where deptno = p_deptno;
return v_dname;
end;
select empno, ename, deptno, get_dname1(deptno) from emp e
where rownum < 4
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "SCOTT.GET_DNAME1", line 4
create or replace function get_dname2(p_deptno IN number) return varchar2 is
PRAGMA AUTONOMOUS_TRANSACTION;
v_dname dept.dname%type;
begin
update dept set dname = dname || '*' where deptno = p_deptno;
commit;
select dname into v_dname from dept where deptno = p_deptno;
return v_dname;
end;
select empno, ename, deptno, get_dname2(deptno) from emp e
where rownum < 4
EMPNO,ENAME,DEPTNO,GET_DNAME2(DEPTNO)
7369,SMITH,20,RESEARCH**
7499,ALLEN,30,SALES***
7521,WARD,30,SALES****
create or replace function get_dname3(p_deptno IN number) return varchar2 is
v_dname dept.dname%type;
begin
lock table emp_copy in share mode;
select dname into v_dname from dept where deptno = p_deptno;
return v_dname;
end;
select empno, ename, deptno, get_dname3(deptno) from emp e
where rownum < 4
EMPNO,ENAME,DEPTNO,GET_DNAME2(DEPTNO)
7369,SMITH,20,RESEARCH**
7499,ALLEN,30,SALES***
7521,WARD,30,SALES****
> -
Auditing DDL and DML statements of selective IP addresses....
Hi all,
DB : 11.2.0.2 64 bit
OS : RHEL 5.7 64bit
Hi all,
I want to audit all DDL and DML statements for some selective IP Addresses or hostnames.
I read about Fine Grained Audit. I got the following code to enable auditing of nondatabase user's actions(Application users).
created policy for client identifier.......
BEGIN
DBMS_FGA.ADD_POLICY(OBJECT_SCHEMA => 'OE',
OBJECT_NAME => 'ORDERS',
POLICY_NAME => 'ORDERS_FGA_POL',
AUDIT_CONDITION => 'SYS_CONTEXT(''USERENV'', ''CLIENT_IDENTIFIER'') = ''Robert''',
HANDLER_SCHEMA => NULL,
HANDLER_MODULE => NULL,
ENABLE => True,
STATEMENT_TYPES => 'INSERT,UPDATE,DELETE,SELECT',
AUDIT_TRAIL => DBMS_FGA.DB + DBMS_FGA.EXTENDED,
AUDIT_COLUMN_OPTS => DBMS_FGA.ANY_COLUMNS);
END;
But I want to audit all DDL and DML statements for a particular schema say ABC from selective IP addresses or hostnames so how can I do this?
Pl suggest.....
Regards,
Andy.Hi,
You could :
1. create a function, say myfunction, returning 1 if you want to audit, 0 otherwise
This function would test sys_context('userenv','ip_address') within the desired IP address to be audited
2. create your fga on the objects you want to audit adding the clause audit_condition=>'myfunction=1'
Nicolas. -
Writing own dml statements in jdeveloper
i need to write my own dml statement in a jdevelopers application. like on saving a purchase form i would like to update stock table as well. Some one told me to write code in DoDML procedure but how ? i mean what statement should i write there ?
lot of possibilities but easy way is to call PL/SQL code i guess you are coming from FORMS background so it would be easy and understandable for you
You can expose PL/SQL package as web-services also you can call stored procedures and functions in ADF
here is the example http://baigsorcl.blogspot.com/2010/05/calling-plsql-procedure-and-function-in.html
doDML() will work at entity level you can call your PL/SQL at doDML as well or as call its method binding -
Calling PLSQL from DML Statements
hello everybody,
i have just a minor "problem". (this confuses me because of the 1z0-147 programming plsql exam)
Oracle Documentation (10G R2 Application Developer's Guide - Fundamentals - 7 Coding PL/SQL Procedures and Packages) says:
The following restrictions are enforced on subprograms:
=> A subprogram called from a DML statement may not read or modify the particular table being modified by that DML statement.
i did some tests but they resulted not in an error (mutating table exception or whatever); so maybe Oracle's documentation is inaccurate here ?
here is an example which works fine (10G R2):
drop table ttestuh
create table ttestuh ( s varchar2(19));
insert into ttestuh values ( 'Oracle' );
create or replace function getVal return varchar2 is
retval ttestuh.s%type;
begin
select s into retval from ttestuh where rownum <2;
return retval;
end;
create or replace function getVal2 return varchar2 is
begin
insert into ttestuh values ( 'ASDF');
return 'ASDF';
end;
insert into ttestuh values ( getval );
insert into ttestuh values ( getval2 );
commit
select * from ttestuh
rows:
Oracle
Oracle
ASDF
ASDFit seems to be that even DML-doing PLSQL calls are allowed when called from an insert statement on the same table.
(for update statements an mutating table exception is raised)
thanks in advance for your opinions
ulliI believe what docs are saying is correct. And also what you are seeing is correct. There may be a small issue in understanding the impact.
SQL> create or replace function fun1
2 return number
3 is
4 begin
5 delete test;
6 end;
7 .
SQL> create or replace function fun1
2 return number
3 is
4 begin
5 update test set owner='amn';
6 end;
7 /
Function created.
SQL> select fun1 from test;
select fun1 from test
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "AMAN.FUN1", line 5
SQL> create or replace function fun1
2 return number
3 is
4 begin
5 insert into test(owner) values('new');
6 end;
7 /
Function created.
SQL> select fun1 from test;
select fun1 from test
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "AMAN.FUN1", line 5
SQL>The mutating error means that the data that you are trying to change is also read by the same session and this means, Oralce can't give a "dirty read" to you. That's why in the case of Update, the mutating error is returned. The insert statement is inserting new data which anyways your select can't see as long as its not committed and with it you haven't changed the existing one that's why its allowed.
SQL> create or replace function fun1
2 return varchar2
3 is
4 a varchar2(10);
5 begin
6 select owner into a from test where rownum<=1;
7 end;
8 /
Function created.
SQL> update test owner=fun1;
update test owner=fun1
ERROR at line 1:
ORA-00971: missing SET keyword
SQL> update test set owner=fun1;
update test set owner=fun1
ERROR at line 1:
ORA-04091: table AMAN.TEST is mutating, trigger/function may not see it
ORA-06512: at "AMAN.FUN1", line 6
SQL>HTH
Aman.... -
PLS-00435: DML statement without BULK In-BIND cannot be used
My requirement
I am dynamically creating a staging table my_stg, and then populate it. Seems simple, but not sure why i get this error,
create table gtest4(myid varchar2(10), mykey varchar2(10));
create table gtest5(myid varchar2(10), mykey varchar2(10));
insert into gtest4 values(1,3);
insert into gtest4 values(2,7);
insert into gtest5 values(5,3);
insert into gtest5 values (1,7);
commit;
/* Formatted on 2012/01/27 17:52 (Formatter Plus v4.8.8) */
CREATE OR REPLACE PROCEDURE px
IS
TYPE rectype IS RECORD (
myid VARCHAR2 (100),
mykey VARCHAR2 (100)
TYPE tabtype IS TABLE OF rectype
INDEX BY BINARY_INTEGER;
rec tabtype;
cur sys_refcursor;
BEGIN
EXECUTE IMMEDIATE 'create table my_stg(myid varchar2(100), mykey varchar2(100)) ';
OPEN cur FOR 'select a.myid, b.mykey
from gtest4 a, gtest5 b
where a.mykey = b.mykey';
LOOP
FETCH cur
BULK COLLECT INTO rec LIMIT 500;
FORALL i IN 1 .. rec.COUNT
EXECUTE IMMEDIATE 'insert into my_stg(myid, mykey) values (rec(i).myid,
rec(i).mykey)';
EXIT WHEN cur%NOTFOUND;
END LOOP;
END;
I compile the above proc, and get
PLS-00435: DML statement without BULK In-BIND cannot be used
the reason I do insert in execute immediate is because the table my_stg does not exist, it is created on the flyI tried the below, used plsql table variables instead of record type
CREATE OR REPLACE PROCEDURE px
IS
TYPE rectype IS RECORD (
myid VARCHAR2 (100),
mykey VARCHAR2 (100)
TYPE tabtype1 IS TABLE OF varchar2(100)
INDEX BY BINARY_INTEGER;
TYPE tabtype2 IS TABLE OF varchar2(100)
INDEX BY BINARY_INTEGER;
rec1 tabtype1;
rec2 tabtype2;
cur sys_refcursor;
BEGIN
EXECUTE IMMEDIATE 'create table my_stg(myid varchar2(100), mykey varchar2(100)) ';
OPEN cur FOR 'select a.myid, b.mykey
from gtest4 a, gtest5 b
where a.mykey = b.mykey';
LOOP
FETCH cur
BULK COLLECT INTO rec1, rec2 LIMIT 500;
FORALL i IN 1 .. rec.COUNT
execute immediate 'insert into my_stg(myid, mykey) values (:1,:2)
using rec1(i).myid, rec2(i).mykey;
EXIT WHEN cur%NOTFOUND;
END LOOP;
END;
I get error
PLS-00103: Encountered the symbol "insert into my_stg(myi
mykey) values (:1,:2)
using rec1(i).myi" when expecting one of the following:
( - + case mod new not null <an identifier>
<a double-quoted delimited-identifier> <a bind variable>
count current exists max min prior sql stddev sum varianc
execute forall merge time timestamp interval date
<a string literal with character set specification>
<a number> <a single-quoted SQL string> pipe
<an alternatively-quoted string literal
Please help -
Will Materialized view log reduces the performance of DML statements on the master table
Hi all,
I need to refresh a on demand fast refresh Materialized view in Oracle 11GR2. For this purpose I created a Materialized view log on the table (Non partitioned) in which records will be inserted @ rate of 5000/day as follows.
CREATE MATERIALIZED VIEW LOG ON NOTES NOLOGGING WITH PRIMARY KEY INCLUDING NEW VALUES;
This table already has 20L records and adding this Mview log will reduce the DML performance on the table ?
Please guide me on this.Having the base table maintain a materialised view log will have an impact on the speed of DML statements - they are doing extra work, which will take extra time. A more sensible question would be to ask whether it will have a significant impact, to which the answer is almost certainly "no".
5000 records inserted a day is nothing. Adding a view log to the heap really shouldn't cause any trouble at all - but ultimately only your own testing can establish that. -
Explain plan on Update statement in function
All,
I have an update statement in a function and my explain plan shows:
"Optimizer" "Cost" "Cardinality" "Bytes"
"UPDATE STATEMENT" "ALL_ROWS" "2" "1" "7"
"UPDATE user.<table_name>" "" "" "" ""
"INDEX(UNIQUE SCAN) <table_name>.<PK_column_cons>" "ANALYZED" "1" "1" "7"
Filtering is on index unique column, but cost is 1 what does that mean?
do i need to change my update statement in function?
Any ideas?
Regards,
~ORAThe cost is the optimizer's measure of how much effort it will take to execute the statement. For any statement the optimizer will evaluate a number of execution plans and choose the one with the lowest cost. I wouldn't worry too much about what it actually "means". However if you want to understand this subject in a lot more detail I would recommend the book Cost-Based Oracle Fundamentals by Jonathan Lewis.
For your update statement the optimizer has chosen to access a single row by the primary key index, which is probably good enough, so you should not need to change it.
The only faster way to access the data would be to use the row's ROWID directly. You would need to have fetched this explicitly in a previous SELECT statement, or you could use it implicitly with the WHERE CURRENT OF syntax for a cursor opened with FOR UPDATE. -
Financial statement with Functional Area
Dear Experts,
We recently implemented SAP in our company.
One problem we have is that our Financial statements are just on GL, our Management wants to see the Financial statement break up by departments (Cost centers) & Projects.
I beleive that this is possible through Functional areas concept, but I don't know completely on how to configure & maintain Functional areas in order to get the Financial statements with Functional area.
Please guide me a complete configuration step.
Many Thanks.
Sunil.Thanks Alice, but I partially disagree with your input.
What is the benefit of maintaining Functional area in the Cost center master data then.
I have seen some slides of Financial statements with Functional are break up by Cost center categories.
Please give more idea on this.
Thanks
Sunil -
Can we do Dml statements on materialize views
I want to know can we do Dml statements on materialize views .If yes, how
Can you? Maybe. Depends on how you created the materialized view. Should you? Maybe. Are you running a multi-master environment? Or are you using materialized views for one-way replication? If you are doing one-way replication, do you want your DML changes to be retained beyond the next refresh of the materialized view?
Justin -
Golden Gate - DML statements are not replicated to target database
Hi,
Testing Environment
Source:
OS: RHEL 4.6, Database: 11gR2, Golden Gate 10.4, ASM
extract ext1
connection to database
userid ggate, password qwerty
hostname and port for trail
rmthost win2003, mgrport 7800
path and name for trial
rmttrail C:\app\admin\GOLDENGATE\dirdat\lt
EXTTRAIL /u01/oracle/goldengate/dirdat/lt
--TRANLOGOPTIONS ASMUSER SYS@ASM, ASMPASSWORD sys ALTARCHIVELOGDEST /u03/app/arch/ORCL/archivelog
--DDL support
ddl include mapped objname sender.*;
--DML
table sender.*;
Target:
OS: Windows 2003, Database: 11gR2, Golden Gate 10.4
--replicate group
replicat rep1
--source and target defintions
ASSUMETARGETDEFS
--target database login
userid ggate, password ggate
--file for discared transaction
discardfile C:\app\admin\GOLDENGATE\discard\rep1_disc.txt, append, megabytes 10
--ddl support
DDL
--specifying table mapping
map sender.* ,target receiver.* ;
I've Successfully setup Oracle Golden Gate test environment as above.
DDL statements are replicating successfully to target database.
while DML statements are not being replicated to target database.
Pl. try to solve the problem
Regards,
Edited by: Vihang Astik on Jul 2, 2010 2:33 PMAlmost ok but how you will handle the overlapping (transactions captured by expdp & captured by Extract too) of transactions for the new table ?
Metalink doc ID 1332674.1 has the complete steps. Follow the "without HANDLECOLLISIONS" approach. -
Hi pals,
I want to know how i can monitor DML statements, i can able to monitor select statments but don't DML statements, is there any way or script in following format:
Executer,Statement,%Completed,%left,Exec_Time,Time_left
Where
Executer is a user who runs the statement
Statement which statement runs
%completed how much DML operation completed
%left how much DML operation left
Exec_Time elapsed time
time_left how much time remaining in complete operation
I really apperciate you pals if you can give me some idea how this can be possible??
Thanks in advance
Hassan KhanHi,
These info can be found in V$SESSION_LOGOPS. But the view isn't populated for every query and sometimes it's a bit weird (I actually had queries that ouput 290% of "work" - parallel query side effect). Also notice that this is for long ops, and not everything will be reported there.
HTH,
Yoann. -
How to Split ddl or dml statement
Hi guys,
i'm using oracle 11.2
i've the following question.
i've a string that can contains multiple ddl or dml statement and i need to split them in more statement.
i.e. i can have a string like the below and i need 2 string each one with a statement:
insert into TEST_KIT_USER1.table1 values (1,'a');
insert into TEST_KIT_USER1.table1 values (2,'b');
otherwise i can have a string like the below and i need 2 string each one with a statement:
create table TEST_KIT_USER1.table2
name char(10),
surname CHAR(10 BYTE)
create table TEST_KIT_USER1.table3
id number,
description CHAR(10 BYTE)
is there a simple way to do this?Have you tried using iMovie?
I know that iMovie HD '06 can do this, I'm not sure if '08 can.
If you have iLife '08, you can download iMovie HD '06 from apple's site here.
Good luck! -
Constructing Database Update DML Statements
This is a very common problem I am sure but want to know how others handle it. I am creating a web application via Servlets and JSPs. I am working with Oracle 10g.
Here's the problem/question.
When I present an html form to a user to update an existing record, how do I know what has changed in the record to create the dml statement? I could just update the entire record with the values supplied via the POST data on submit but that does not seem right since maybe only 1 out of 10 fields actually changed. This would also write needless audit and logging information to the database. I have thought about comparing the Request parameters sent with the post with the original java bean used to populate the form in the first place by adding it back to the request as an attribute. Is this the only way to do it or is there a better way?
Thanks everyone,
-BrianWhat database drivers are you using? I recall there being some bug in
sp2 that caused delayed transaction commits for a very specific
combination of transaction settings and database drivers.
I think it was third-party type II Oracle drivers and local
transactions, but I'm not sure.
In any case, I'd contact support as there is a patch available.
David
Gurjit wrote:
Hi all,
I have posted something of this sort earlier too. The problem is that
the database is not reflecting what has been updated using queries from the
application.
THe structure of the application is as follows.
DB = Oracel 8.1.6
Web Server = iPlanet 4.0
App Server = iPlanet 6.0 sp2
The database is connected to via the EJB's. No Database transactions are
being used except for Bean transactions which are container managed. The
setAutoCommit flag is set to true. Each query is a transaction. The jsp's
call these ejb's through wrapper classes. As stated earlier the database
updates (Inserts, update, delete statements) are not getting reflected in
the database immediately. The updates happen after a gap of about 7-10
minutes. Why is this sort of behaviour coming up. This is almost like batch
updates happening on the database. Is there a setting in IPlanet for
removing this kind of problem.
Regards,
Gurjit
Maybe you are looking for
-
Hello. Today I downloaded some songs from a YouTube converter. I selected the songs I wanted and tranferred them from my desktop into iTunes. I clicked on "Music", which I believe is where ALL of my other songs that I already had on my iPod, should b
-
Could not initialize the application's security component
Hello, I installed Firefox 3, I did check for update, but 4.0.1 when running show me this message: "Could not initialize the application's security component. The most likely cause is problems with files in your application's profile directory. Pleas
-
Question concerning cRIO function
Hello, I am a newcomer in using cRIO controllers. I made a project containing two vis, one running on my PC and another one running on cRIO controller (for the communication I used shared variables). Please note that in the PC vi there is a timed loo
-
Web Services with XMLBeans Validation
Hi, I am very new to XMLBeans and Web Services. From my understanding, schemas can be used to validate an xml document. However, I would like to find out: 1. Can I validate my web service inputs againest the generated XMLBeans objects/schema? 2. How
-
Hey i want to plot a already logged text file data to waveform chart. Is there any way that this can be done by selecting the file and running the vi to plot data.Is there any specific function??