Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Munzer.

Asked: January 11, 2002 - 9:18 pm UTC

Last updated: May 14, 2008 - 10:25 am UTC

Version: 8i

Viewed 1000+ times

You Asked

Tom:

I have a simple update statement in a PL/SQL procedure that updates a record. IT works fine, however when I add the "WHERE" clause to make sure I only update when no user updated the record while I am updating it fails. I was wondering whether it was due to updating a null column since you have to use "is" instead of "=".

create or replace procedure do_update (
p_log_no VARCHAR2 DEFAULT NULL,
p_old_name VARCHAR2 DEFAULT NULL,
p_new_name VARCHAR2 DEFAULT NULL,
p_old_DOB VARCHAR2 DEFAULT NULL,
p_new_DOB VARCHAR2 DEFAULT NULL,
p_old_note VARCHAR2 DEFAULT NULL,
p_new_note VARCHAR2 DEFAULT NULL )
IS
v_log_no NUMBER(10);
v_DOB DATE;
Begin
v_log_no:=to_number(p_log_no);
v_old_DOB:=to_date(p_old_dob,'MM-DD-YYYY');
v_new_dob:=to_date(p_new_dob,'MM-DD-YYYY');

update intreq set name = p_new_name,
dob = v_new_dob,
note= p_new_note
WHERE log_no = v_log_no and
rtrim(name) = rtrim(p_old_name) and
dob = v_old_dob and
rtrim(note) = rtrim(p_old_note);

2. I saw in an oracle web book that you can use
select ename,job into dbename,dbjob from emp where empno=empnumber for update nowait;

to lock the row. Then they look for ORA-000054 to tell other users that record is locked.

I though in a web environemnt you can not really lock rows as the connection is maintained per page only.

can you do it?

THank you,



and Tom said...

1) please define "fails" for me. what exactly are your symptons.

Yes, if any of p_old_name, v_old_dob, p_old_note are NULL, the equals will never be true (it won't be false either, it'll be UNKNONW)

I would

1) select the rowid out in the procedure that calls this procedure. Use htf.escape_sc( rowid ) when you save it as a hidden field on the form as the rowid contains +'s and other characters that can mess up GET or POST data.

2) code the update as:


update t set c1 = p_new_c1, c2 = p_new_c2
where rowid = p_rowid
and (c1 = p_old_c1 OR (c1 is null and p_old_c1 is null))
and (c2 = p_old_c2 OR (c2 is null and p_old_c2 is null));

As for the select for update, in a stateless environment you cannot use it to lock rows from page to page, this is true. You can (and when necessary should) use it in your transactions to prevent concurrent updates to the same record. There are still times when you might need it in a single atomic transaction -- to read the data out, lock it, update something else, then come back and update the record you just read out for example.


Rating

  (21 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Update on web application

Munzer, January 12, 2002 - 1:00 pm UTC

Tom:

1. What i mean by fail is that it does not do an update for the record.
What is" htf.escape_sc(rowid) " used for? Can't I use the primary key for the record instead?

2. Can you also do the "WHERE clause" in an if statement before you do the update such as:

If name=p_old_name and dob=v_old_dob then UPDATE ..... ;

3. You say I should lock record to prevent updates to the same record. Does this apply when I am using "STATEFUL" web connection. I thought in a HTML/PL-SQL application you can never lock record in any way.

If this is the case then do i need a "WHERE" clause in my update statement since I am locking record anyway?

Can I test this locking feature on the web?do you know of any documentation or examples on this subject?

Thanks




Tom Kyte
January 12, 2002 - 1:18 pm UTC

1) you can use the primary key -- but rowid is faster then primary key, rowid is always there, rowid is a known length, rowid is reliable.

htf.escape_sc() is used to escape special characters, things that will break HTML if you don't escape them.  If you are programming web stuff with HTP and don't know about this -- you are in BIG trouble. 

For example, insert a row into a table that has this in a string:

  insert into t values ( 'This is what a sqlplus prompt looks like "SQL>" ' );

Now, create a form to edit that!  The > is going to mess things up horribly.  If we htf.escape_sc before we print out using htp:

ps$tkyte@ORA817DEV.US.ORACLE.COM> select htf.escape_sc( 'This is what a sqlplus prompt looks like "SQL>"' )
  2  from dual
/  3  

HTF.ESCAPE_SC('THISISWHATASQLPLUSPROMPTLOOKSLIKE"SQL>"')
-----------------------------------------------------------------------------------------------------------------------------------
This is what a sqlplus prompt looks like "SQL>"


it ESCAPES things that will mess up HTML -- quotes, >, +, whatever...


You need to revisit ALL of your code to make sure you are escaping text before putting it in HTML else you run the risk of having a very bad thing happen to your data someday (lost data, incorrect data, etc)

2) I fail to see where an if statement comes into play.  We don't have any name, dob variables to compare to???

again, you would need to add the OR condition for NULLs as well.

3) In an HTML plsql application - the second you updated that record, you locked it.  Its locked until your transaction ends.  There is no difference here.  What you cannot do in a STATELESS environment is lock a record in one page, send the page back to the browser and expect that record to remain locked.

You need a where clause in an update to avoid updating records you don't mean to update.

There is no "locking feature for the web", locking is NO DIFFERENT on the web then anywhere else.  It is just that on the web -- you typically do not maintain state, hence you do not maintain locks, hence you must use a technique such as above when updating to ensure the data did not change.

If you have my book -- i do go into great detail on this.  This technique you are doing is known as OPTIMISTIC locking.  In a client server environment with a stated connection we would typically use  PESSIMISTIC locking instead.  I cover how to do it, what it is and more in the book. 

htf.escape_sc( )

Munzer, January 13, 2002 - 12:31 pm UTC

Tom:

1. When you say it is faster to update using rowid rather than primary key, are we talking about milliseconds. let us say record length is 500 characters?

2. I have not had a problem not using htf.escape( ) because maybe I was not testing data entry with special characters.

However, are you saying to use it always before you do "SELECT", INSERT, UPDATE, or DELETE.

If you do it before insert then it will it still save those characters in the database?

THank you

Tom Kyte
January 13, 2002 - 1:08 pm UTC

1) if you use the primary key the access plan will probably be:

step 1) index range scan (unique) on the primary key index
step 2) using the rowid we just found in step 1, table access by rowid

using the rowid, we can simply do step 2, go directly to the data.


2) correct -- the first time you get any data with quotes, &, >, <, etc -- you will have grievous problems.


You use HTF.ESCAPE_SC when you are calling htp.p -- after you selected, as you are generating the page. It is an HTML formatting issue. Just do it when you print the page and thats it.

Followup on htf.escape_sc

Munzer, January 14, 2002 - 9:43 pm UTC

Tom:

I did try inserting values of '> and <' in a table and retrieved it later using htp.p and it came fine. However if you use it in " " it will not give you data.

However, I am a little ocnfused on how and when you use this function.

If you are inserting data from a web screen, I guess you do not use use it unless you are worried about passing the data from the first page to the 2nd page in the URL.
IF user enters (&, >, <, + ) it seems it goes fine to the insert PL/SQL program. If you want some values hidden would you use?
HTP.FormHidden('dept',htf.escape_sc(p_dept)); -- to pass hidden values
HTP.FormText('p_name',20,20,htf.escape_sc(p_name); --
to pass unhidden values?


2. If you are updating data and you select the record from the database then are you saying that you always use the function like:

FOR x in (Select ... from tab )
LOOP
htp.p(htf.escape_sc(x.col1) );
END

Is this correct?

3. Do you know of any examples reference on using this package?

Thanks,


Tom Kyte
January 15, 2002 - 8:23 am UTC

sigh, cause you can do it once does NOT mean it works.

Trust me -- if your text can have <, >, and other special characters in it -- you are heading for DISASTER unless you escape it.

Consider if the value in the database is:

blah blah " > blah blah blah



and you do this:


htp.p( '<input type=text value=" || p_variable || '">' );

Normally, that'll print out:

<input type=text value="Your Value">

But it can now print out:

<input type=text value="blah blah " > blah blah blah blah ">

See that THAT does to your form!!! the proper way to print that out is:

<input type=text value="blah blah &quot; &gt; blah blah blah blah ">


If the USER enters &, <, > etc -- it goes fine cause the BROWSER encodes the data on the way up and the app server is responsible for decoding it (so you'll never get &gt; unless that is what the END USER typed in.

If you think this sort of data never gets entered -- just look at this followup -- if we did NOT escape this text, you would not be reading this -- it would be garbage (do a view source on this page to see it escaped).


I would say in generate that ALL calls to htp.formXXXXXX should use htf.escape_sc on the text to protect yourself.

2) yes.

3) the documentation?



Is there support for 'umlaut's?

Dieter, February 20, 2002 - 4:58 am UTC

Hello, Tom

Oracle 8.1.7#

I tried to encode several other characters as well using htp.escape_sc, mostly German umlauts.

E.g. my last name is 'Bücherl', and I expected to receive
to 'B&uuml;cherl' or 'B&#252;cherl', but this didn't get
encoded .

The same applies to other language specific characters.

I wrote a wrapper which encodes the usual suspects,
but I would prefer to have a genuine solution.

Did I overlook something?


Thanks

Dieter

Tom Kyte
February 22, 2002 - 10:06 am UTC

You will have to write your own wrapper. The supplied one does not do that.

Encoding blanks in NEtscape

Munz, July 03, 2002 - 11:11 pm UTC

TOm:

1. My web application works just fine in Internet Explorer 6. However because some users have NEtscape 4.7 I had to test it using it too.

The problem I am seeing is that because I pass a user_id from one page to another, if the user id has two words separated by a space, IE puts a %20 while NEtscape only passes first word or sometimes two words separated by space.

THe query does not work becuase it uses that user id.

DO you know what should I do to substitute or encode those blank when passing parameters from one page to another in NEtscape.

Tom Kyte
July 04, 2002 - 10:55 am UTC

Arg, I hate IE for this reason (i use netscape).

IE is hiding your error at the expense of every other browser.

YOU are responsible for URL encoding YOUR strings.  YOU have a bug in your code!!!

Here is a handy little function you can use:


ops$tkyte@ORA817DEV.US.ORACLE.COM> create or replace function urlencode( p_str in varchar2 ) return varchar2
  2  as
  3          l_tmp   varchar2(12000);
  4          l_len   number default length(p_str);
  5          l_bad   varchar2(100) default ' >%}\~];?@&<#{|^[`/:=$+''"' || chr(10);
  6          l_char  char(1);
  7  begin
  8          if ( p_str is NULL ) then
  9                  return NULL;
 10          end if;
 11  
 12          for i in 1 .. l_len loop
 13                  l_char :=  substr(p_str,i,1);
 14                  if ( instr( l_bad, l_char ) > 0 )
 15                  then
 16                          l_tmp := l_tmp || '%' || to_char(ascii(l_char), 'fm0X');
 17                  else
 18                          l_tmp := l_tmp || l_char;
 19                  end if;
 20          end loop;
 21  
 22          return l_tmp;
 23  end;
 24  /

Function created.



Use that on all fields you pass as data to links and it'll do the right thing:

ops$tkyte@ORA817DEV.US.ORACLE.COM> select urlencode( 'user name' ) from dual;

URLENCODE('USERNAME')
-----------------------------------------------------------------------------------------------------------------------------------
user%20name


This is not a Netscap'ism -- this is the way the HTTP protocol is defined to work (and MS is "breaking" that protocol, again, as usual)
 

URL Encoding

munz, July 07, 2002 - 1:24 pm UTC

Tom:

Thanks a lot for excellent help.

1. If I have an HTML form with 30 text fields, and let us say some date and number fields, DO I have to use this function for each SUBMIT. E.g.

htp.formText(urlencode(i_name),40,40,null);
or
htp.p('<input name="'||urlencode||p_name||'" size=40 maxlength=40 values=null>;


or is it only for when calling hardcoded links?
2. I have created so many forms without the urlencode. Does it mean I have to visit each PL/SQL procedure and use that function for each submit.

3. Would not using the "post" method in a form automatically does that while "get" does not.





Tom Kyte
July 07, 2002 - 2:23 pm UTC

you do not need to urlencode the names in general -- especially if you are using PLSQL -- as plsql only accepts characters that are OK in urls.

it is the VALUE part you want to urlencode.


You use it with links. You don't need to use it in a form -- there you need to HTF.ESCAPE_SC the strings (consider an input item whose default value contains &, ", or > for example -- that would really mess things up.


2) only if you want things to work right all of the time. If any of your field values can contain &, ", <, > -- you'll want to make sure they are htf.escape_sc'ed and if they are in a htp.anchor call, you want to make sure they are URLENCODED.

3) doesn't matter -- FORMS = escape_sc, ANCHORS = urlencode.



web insert

mo, January 08, 2003 - 9:46 pm UTC

Tom:

I have a we bform that displays blank entries in tabular form where user can enter up to 10 records and then hits save to save it. the table is

create table invent as
(a varchar2(10),
b varchar2(10),
user_id varchar2(10),
creation_date date );

a+b make a primary key. The problem is that after user enters several records I show him a confimration page with all records he entered. How would I select the records that he inserted in that page only. I am thinking of adding a column "key" that would have a sequence, same value for all records inserted and then query the table for that sequence value. Would you use a temporary table here instead or do it in a different way?


update

m, January 22, 2003 - 7:02 pm UTC

Tom:

are you sure about the update statement for columns that have null values. I did the same thing for birth_date below but update fails when I have a null value in that record.

UPDATE inventory
SET warehouse_id = i_warehouse_id(i),
stock_number = i_stock_number(i),
effective_Date = to_date(i_effective_Date(i),'dd-mon-yyyy'),
storage_Code = i_storage_code(i),
quantity = i_quantity(i),
birth_date = to_date(i_birth_date(i),'dd-mon-yyyy'),
user_id = i_user_id,
creation_date = sysdate
WHERE warehouse_id = i_old_warehouse_id(i) and
stock_number = i_old_stock_number(i) and
trunc(effective_date) = to_Date(i_old_effective_date(i),'dd-mon-yyyy') and
storage_code = i_old_storage_code(i) and
quantity = i_old_quantity(i) and
(trunc(birth_date) = to_date(i_old_birth_date(i),'dd-mon-yyyy') or (i_old_birth_date(i) is null and i_birth_date(i) is null) );


Tom Kyte
January 23, 2003 - 7:42 am UTC

umm, so, can you define "update fails" -- got an example to look at, error code/msg, anything (throw me a bone here...)

but:
(trunc(birth_date) =
to_date(i_old_birth_date(i),'dd-mon-yyyy') or (i_old_birth_date(i) is null and
i_birth_date(i) is null) );

doesn't look right -- shouldn't that be:

(trunc(birth_date) = to_date(i_old_birth_date(i),'dd-mon-yyyy')
or (i_old_birth_date(i) is null and birth_date is null)
)


update

mo, January 23, 2003 - 10:56 am UTC

Tom:

I do not see any difference between your statement and mine other than you misses the (i) for i_birth_Date. It is an array so I have to use (i).

I think I know why the update was failing:

update t set c1 = p_new_c1, c2 = p_new_c2
where rowid = p_rowid
and (c1 = p_old_c1 OR (c1 is null and p_old_c1 is null))
and (c2 = p_old_c2 OR (c2 is null and p_old_c2 is null));

If p_old_c1 is null and c1=value then the above will never update. I do not see why did not you write:

and (c1 = p_old_c1 OR (p_old_c1 is null) )

This should update in both cases:
1. c1 is not null and p_old_c1 is null.
2. c1 is null and p_old_c1 is not null.

do you agree?


Tom Kyte
January 23, 2003 - 11:18 am UTC

and (c1 = p_old_c1 OR (c1 is null and p_old_c1 is null))

I compare:

c1 = p_old_c1 --> database column to variable
OR
c1 is null and p_old_c1 is null) --> database column to NULL and variable to NULL


You have:

(trunc(birth_date) = to_date(i_old_birth_date(i),'dd-mon-yyyy') --> db to var
or
(i_old_birth_date(i) is null and i_birth_date(i) is null) ); --> var & var


You are saying:

if the birth_date = variable OR (both the old and the new VARIABLES are null)


which doesn't make sense. Your code is *wrong*. You want to update the row IF

birth_date = old_birth_date OR
(birth_date is NULL nad old_birth_date is NULL)

you said:

If p_old_c1 is null and c1=value then the above will never update. I do not see
why did not you write:

that is 100% correct. If p_old_c1 is NULL and c1 is not NULL then -- hey, someone else UPDATED THE DATA and the entire point of this exercise is to avoid blindly overwriting someone elses changes. This means someone come along AFTER we read the data out - changed the column C1 and we are coming back and trying to overwrite their changes without ever looking at them





update

mo, January 23, 2003 - 12:02 pm UTC

Thanks, you are 100% correct.

update

mo, January 23, 2003 - 6:25 pm UTC

Tom:

I am creating a list of update statements by running select on a table as :

  1  select 'update shipment set state = '''||state||''''||
  2  ', zip = '''||zip||''''
  3*  from shipment
SQL> /

update shipment set state = 'OH', zip = '45215-1190'

When I want to add "WHERE STATE = 'OH' as a string at the end it does not like it.

select 'update shipment set state = '''||state||''''||
', zip = '''||zip||''''
 from shipment  ||'where state = ''OH'' '

ERROR at line 3:
ORA-00933: SQL command not properly ended

Any hints on doing this?
 

Tom Kyte
January 23, 2003 - 8:18 pm UTC

look twice at what you are doing.

do you want to build an update with a where? if so, your where is in the wrong place.

do you want to where on the select? if so, your where shouldn't be a character string literal concatenated onto the select, it should "just be there" like from shipment is.

thanks for the url encoding function!

Dave, April 21, 2003 - 6:48 pm UTC

I was in the middle of writing my own url encoding to encode some urls so that i can have a "breadcrumb trail" of links so a user can backtrack through my pl/sql web app. I was using owa_pattern.change to fix the symbols that were screwing up my links but this function does it in a less piecemeal fashion.

again, you rock.

update

mo, July 02, 2004 - 5:05 pm UTC

Tom:

Does "update" internally do delete/insert.

I created a "Update" form by using the "INSERT" and deleting the data before the insert. Would this be inefficient? Is using "UPDATE" better.

Problem is that is easier because if user had two items/records and edited to only one ite, then you have to update 1 and delete the other. it is easier to delete the two and insert one.



Tom Kyte
July 02, 2004 - 7:01 pm UTC

no, update does an update.

using update is much more efficient than delete+insert.

but if you have multiple things like that, where you are editing a mess of things, sometimes the coding of the delete+insert is so much easier -- it can be worth it.

update

mo, July 20, 2004 - 10:51 am UTC

Tom:

Can you update one table A based on a value in a column in table B. Table A and B have a common key and can be joined.

Update table A
set A.col1 = 'A'
where pk_col = 'value'
and table_B.col ='Y';


Alessandro Nazzani, November 02, 2004 - 12:04 pm UTC

You said

<quote>
1) select the rowid out in the procedure that calls this procedure.  Use 
htf.escape_sc( rowid ) when you save it as a hidden field on the form as the 
rowid contains +'s and other characters that can mess up GET or POST data.
</quote>

and

<quote>
ps$tkyte@ORA817DEV.US.ORACLE.COM> select htf.escape_sc( 'This is what a sqlplus prompt looks like "SQL>"' )
  2  from dual
/  3  

HTF.ESCAPE_SC('THISISWHATASQLPLUSPROMPTLOOKSLIKE"SQL>"')
</quote>

Ok, but

_system_@PMED10G> select htf.escape_sc( 'This is what a sqlplus prompt looks like "SQL+>"' )
  2   from dual;

HTF.ESCAPE_SC('THISISWHATASQLPLUSPROMPTLOOKSLIKE"SQL+>"')
----------------------------------------------------------------------------------------------------
This is what a sqlplus prompt looks like &quot;SQL+&gt;&quot;

Do I have to roll my own escape_sc to catch the + character?

Alessandro 

Tom Kyte
November 03, 2004 - 5:39 am UTC

hmm, could have sworn that in the past, htf.escape_sc did that, but this is the routine I use for encoding things that might appear in a URL:

create or replace function urlencode( p_str in varchar2 ) return varchar2
as
l_tmp varchar2(12000);
l_len number default length(p_str);
l_bad varchar2(100) default ' >%}\~];?@&<#{|^[`/:=$+''"' || chr(10);
l_char char(1);
begin
if ( p_str is NULL ) then
return NULL;
end if;

for i in 1 .. l_len loop
l_char := substr(p_str,i,1);
if ( instr( l_bad, l_char ) > 0 )
then
l_tmp := l_tmp || '%' || to_char(ascii(l_char), 'fm0X');
else
l_tmp := l_tmp || l_char;
end if;
end loop;

return l_tmp;
end;
/


Alessandro Nazzani, November 03, 2004 - 7:19 am UTC

Thanks, we already use URLEncode for links.

But my question was about form fields: perhaps the + character is harmless in this case.

So I guess my next question is: what "other characters" can a rowid contain and are they caught by escape_sc?

Thanks for your patience.

Alessandro

Tom Kyte
November 03, 2004 - 7:25 am UTC

the plus should be -- the browser would encode it.

it is when they are used in a url -- not just in html, i mispoke.

escape_sc

A reader, May 10, 2008 - 8:38 am UTC

excellent

escpae_Sc

A reader, May 12, 2008 - 4:23 pm UTC

Tom:
Did you notice that in your example above if you add "'" to prompt word it fails

select htf.escape_sc( 'This is what a sqlplus prompt's looks like "SQL>"' ) from dual
SQL> /
ERROR:
ORA-01756: quoted string not properly terminated

Is there an issue with the function escaping "'".


Tom Kyte
May 13, 2008 - 10:16 am UTC

you have to use two quotes when YOU code a string literal (if that was a bind, it would not be so)

that is a SQL'ism - if you want a ', you use '' (or the new 10g quoted literal format)


remove escape_sc from the equation - just try to select that STRING.

Note: this applies ONLY TO LITERALS - not to normal strings used in binds. Your code needs to do nothing about single quotes. Only when YOU type code in (or use string concatenation instead of properly binding) would you need to be concerned about a quote.

escape

A reader, May 13, 2008 - 4:26 pm UTC

Tom:

just a little confused on your comment.

We have an html form that users input data and we save that to the 9iR2 Oracle database. We read your column and used this nice function in every dynamic HTML or XML page we build from data in DB.

so we would have something like this

SELECT cust_id,comments INTO v_cust_id,v_comments
FROM orders WHERE order_id = 100;

OWA_UTIL.mime_header('text/xml',TRUE);
htp.p('<?xml version="1.0" encoding="ISO-8859-1"?>');
htp.p('<ROW>');
htp.p(<CUST_ID>'||v_cust_id||'</CUST_ID>');
htp.p('<COMMENTS>'||htf.escape_sc(v_comment)||'</COMMENTS>);
htp.p('</ROW>');

Would not this fail when user enter a single quote or the string I showed above in the comment.

2. How can we see the characters this function escapes? We do not see it listed under functions in TOAD. Is it a built in oracle function.
Tom Kyte
May 14, 2008 - 10:25 am UTC

quotes in a string variable are NOTHING SPECIAL.

Like I said - it is when YOU (a human) types in a query with a string literal that YOU have to think about this.

Look - when I insert into the table using a STRING LITERAL - that I type in - yes, we have a problem and have to quote it correctly.

However, once that data is in a variable - it is just data in a variable, the quote is not part of the EXECUTABLE CODE (like it was when we just typed it in)

In general, short of a script you write, you need not worry about quotes in SQL or PLSQL - it is only when you build a string and execute it that you might have to worry (if you do not BIND the string in)

ops$tkyte%ORA10GR2> create table t
  2  as
  3  select 1 cust_id, q'|how's this for a string with 'quotes' galore|' descript
  4  from dual;

Table created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> select * from t;

   CUST_ID DESCRIPT
---------- --------------------------------------------
         1 how's this for a string with 'quotes' galore

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> @owainit
ops$tkyte%ORA10GR2> declare
  2          nm      owa.vc_arr;
  3          vl      owa.vc_arr;
  4  begin
  5          nm(1) := 'WEB_AUTHENT_PREFIX';
  6          vl(1) := 'WEB$';
  7          owa.init_cgi_env( nm.count, nm, vl );
  8  end;
  9  /

PL/SQL procedure successfully completed.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> begin
  2          for x in ( select * from t )
  3          loop
  4                  htp.p('<?xml version="1.0" encoding="ISO-8859-1"?>');
  5                  htp.p('<ROW>');
  6                  htp.p('<CUST_ID>'||x.cust_id||'</CUST_ID>');
  7                  htp.p('<COMMENTS>'||htf.escape_sc(x.descript)||'</COMMENTS>');
  8                  htp.p('</ROW>');
  9          end loop;
 10  end;
 11  /

PL/SQL procedure successfully completed.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> exec owa_util.showpage
Content-type: text/html
Content-length: 144
<?xml version="1.0" encoding="ISO-8859-1"?>
<ROW>
<CUST_ID>1</CUST_ID>
<COMMENTS>how's this for a string with 'quotes' galore</COMMENTS>
</ROW>

PL/SQL procedure successfully completed.

escape

A reader, November 08, 2008 - 12:59 am UTC


update

A reader, November 25, 2009 - 6:29 pm UTC


More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library