Inside Oracle APEX by Patrick Wolf

SQL embedded into PL/SQL

A few days ago I spoke with another developer about SQL embedded into PL/SQL code and how function calls are handled in the WHERE clause of SQL statements. There is sometimes confusion who (PL/SQL engine or SQL engine) is executing it, I thought it's a good idea to write a posting about it.

Last year I have already blogged about it in Caution when using PL/SQL functions in a SQL statement, but that was in the context of writing a stand alone SQL statement for a report, ... but what actually happens if you have a SQL embedded into PL/SQL like the following example procedure code in a package
PROCEDURE processEmps
( pDepartmentId IN NUMBER
)
IS
BEGIN
FOR rEMP IN
( SELECT EMPLOYEE_ID
FROM EMPLOYEES
WHERE SALARY > getAvgDeptSalary(pDepartmentId)
)
LOOP
NULL;
END LOOP;
END processEmps;
(Note: getAvgDeptSalary isn't a very good example, because you could also do that with SQL only, but it's just an example)

Very simple. A function in the WHERE clause which uses the procedure parameter pDepartmentId. What would you expect how the code/SQL is executed?

Do you expect the code is executed in the following order?
  1. Procedure processEmps is called
  2. Function getAvgDeptSalary gets executed by the PL/SQL engine, because the PL/SQL engine has already all input parameters for the function call. No values from the query are needed. The result gets stored into an internal temporary bind variable.
  3. Context switch to the SQL engine which executes the query on EMPLOYEES, restricted to SALARIES greater than the value in internal temporary bind variable.
Sorry you are wrong!

The hole SQL statement is handed over to the SQL engine, which then does a call to the getAvgDeptSalary function. That could be one time if you are lucky and the optimizer is clever enough, but it could also be for each row which is processed by the query!!! So it's the same processing as already described in my Caution when using PL/SQL functions in a SQL statement! You can also easily identify that behavior by yourself, because there are some restrictions in the usage of function calls in the WHERE clause:
  • You can only use public functions.
  • You can't use the non-positional syntax (at least in < 11g) for the function parameters.
That's because the SQL engine can only use public PL/SQL functions and can't handle the non-positional syntax for parameters.

So if you have somewhere in your code such function calls (like the V or NV functions in Oracle APEX), be aware that this could be a performance bottleneck! Do the function call before the SQL statement and use a variable to restrict the query.

Labels: , , ,


« ... Read full posting ... »

What is the foundation of Oracle Application Express (APEX)?

You are correct, it's PL/SQL! I'm sure you knew that ;-)

So that means every improvement which is done for PL/SQL is good for us Oracle APEX developers, like the function result cache, the continue statement and much more which have been introduced in Oracle 11g.

Did you know that there is a new initiative by Steven Feuerstein and the Apex Evangelists guys to bring new enhancement requests to the attention of the Oracle PL/SQL product management?

Check out the new "I love PL/SQL, and ..." web-site and help to improve PL/SQL!

Labels:


« ... Read full posting ... »

Oracle 11g: Native Web Services

Just stumbled across an interesting paragraph in the New Features in Oracle XML DB for Oracle Database 11g Release 1 about Database Native Web Services.

The feature didn't get that much attention yet on the Oracle 11g related blog postings, but according to the description it's a real nice improvement compared to the 10g solution.

So what is it all about?

It allows you to publish your PL/SQL packages/procedures/functions as a web service with zero coding and zero deployment effort!

Maybe you have already heard of the SOA (service-orientated architecture) hype and probably your manager or the Java guys have already asked you how you want to participate with your old legacy PLSQL/Oracle APEX code in the "new and everything is now better" world of SOA and BPEL. This native integration of web services into the database is the answer. Probably you even have to do less work then the Java guys to expose your business service... ;-)

Another goody is that you don't need the additional application server infrastructure anymore as you had to have it with the existing JDeveloper solution which generated a Java wrapper for your PL/SQL package. That's especially useful in an Oracle APEX environment where you don't need an application server anymore. Another moving piece is gone...

Really looking forward to try out Oracle 11g myself.

See also my related posting Oracle 11g more infos.

Update: Check out Paul Gallagher's blog posting First Tests of 11g Native Web Services for more information about this feature.

Labels: , ,


« ... Read full posting ... »

What is your favorite PL/SQL development environment?

Mine is PL/SQL Developer from allroundautomations.

Why?

Because it's a PL/SQL development tool focused on PL/SQL development. Most of the other tools like TOAD or SQL Developer which I also used in the past, have great DBA/query functionality, but suck from a "state of the art" programming point of view.

Sure they all have a PL/SQL editor with auto replace and template support. In the meanwhile SQL Developer is now also able to do file based PL/SQL development. In one of the first versions you could just edit the packages stored in the database repository. Can you imagine doing professional development where your code is just stored in the database?!?! Me not! That was a killer criteria not to use it at that time - independent if it was for free or not.

So what makes PL/SQL developer different compared to TOAD and SQL Developer?

It's the code complete/code insight/auto complete or however the IDEs call it and which you are used to from modern Java/.Net/... IDEs. Now you will say: "Hey, TOAD and SQL Developer have that too!". Yes they have, but just a basic one which only offers auto complete for tables/views.

The auto complete I'm talking about knows about the PL/SQL code you wrote. If works for local variables, packages, procedures of the packages, parameters of this procedures, ... If you are getting used to to press Alt+space to complete what you are typing, it can really speed up your development!

I'm not talking about the other features like refactoring support, variable highlighting and so on what the tool also offers. Check it out by yourself.

If you are used to TOAD, changing to this new IDE can be a little bit irritating at the beginning, because the way windows are handled is different and you have to get used to the SQL Window which requires a semi-color for SQL statements.

But it's worth trying out - from a PL/SQL developer point of view - a DBA should stay with his TOAD/SQL Developer.

BTW, I'm not paid for this article. I'm just a satisfied user of that tool and I see to often unproductive PL/SQL development with the wrong tools.

Update: Another useful feature is the integrated compiler which shows you warnings for unused variables/parameters or if the naming doesn't comply to your styleguide.

Labels: ,


« ... Read full posting ... »

Sending a SMS to a mobile phone

Today I read an article on Grant Rolands blog about sending a SMS from Oracle Forms through a Web-Service.

I thought it would be nice to have the same in APEX and PL/SQL, too. For example if you have a system failure or get a new order in your shop...

Grant is using a Web-Service provided by Esendex, but I'm sure there are others service providers available too. First I thought using the offered Web-Service and create a PL/SQL wrapper for it our use the Web-Service feature of APEX.

But I decided to go with the simple POST version which is also offered by them. Because why invoke all the Java stuff when there is also a simple version available. The APEX web-service couldn't be used, because then you would not be able to call it from PL/SQL.

The code is quite straight forward. Get a free account, replace the constant values in the example procedure and you are ready to go!

Note: If you have a proxy then you have to uncomment the proxy line. There is also a secure version available which uses HTTPS, but that requires a wallet, ... and I just wanted to demonstrate that it works. The error handling of the procedure could also be improved, but hey, it's just a demonstration. :-)

Have fun waking up your operators/DBAs in the night! :-)

To send a SMS just call the procedure with
BEGIN
sendSMS('+436991812345','this is a test');
END;
Here comes the example procedure:
CREATE OR REPLACE PROCEDURE sendSMS
( pRecipient IN VARCHAR2
, pBody IN VARCHAR2
)
IS
ESENDEX_USERNAME CONSTANT VARCHAR2(40) := 'your_username';
ESENDEX_PASSWORD CONSTANT VARCHAR2(40) := 'your_password';
ESENDEX_ACCOUNT CONSTANT VARCHAR2(40) := 'your_account';
--
vRequest Utl_Http.req;
vPostText VARCHAR2(500);
vResponse Utl_Http.resp;
vResponseText VARCHAR2(2000);
vErrorText VARCHAR2(200);
BEGIN
----------------------------------------------------------------------------
-- Build text for the post action.
-- For a field description, see
-- http://www.esendex.com/secure/messenger/formpost/SendSMS.aspx
----------------------------------------------------------------------------
vPostText :=
'EsendexPlainText=YES' ||CHR(38)||
'EsendexUsername=' ||Utl_Url.escape(ESENDEX_USERNAME, TRUE)||CHR(38)||
'EsendexPassword=' ||Utl_Url.escape(ESENDEX_PASSWORD, TRUE)||CHR(38)||
'EsendexAccount=' ||Utl_Url.escape(ESENDEX_ACCOUNT, TRUE)||CHR(38)||
'EsendexRecipient='||Utl_Url.escape(pRecipient, TRUE)||CHR(38)||
'EsendexBody=' ||Utl_Url.escape(pBody, TRUE);
----------------------------------------------------------------------------
-- if you need to set a proxy, uncomment next line.
----------------------------------------------------------------------------
/* Utl_Http.set_proxy('proxy.it.my-company.com', 'my-company.com'); */
----------------------------------------------------------------------------
-- Send SMS through the Esendex SMS service.
----------------------------------------------------------------------------
vRequest := Utl_Http.begin_request
( url => 'http://www.esendex.com/secure/messenger/formpost/SendSMS.aspx'
, method => 'POST'
);
Utl_Http.set_header
( r => vRequest
, name => 'Content-Type'
, value => 'application/x-www-form-urlencoded'
);
Utl_Http.set_header
( r => vRequest
, name => 'Content-Length'
, value => LENGTH(vPostText)
);
Utl_Http.write_text
( r => vRequest
, data => vPostText
);
vResponse := Utl_Http.get_response(vRequest);
IF vResponse.status_code = '200'
THEN
Utl_Http.read_text(vResponse, vResponseText);
--
IF vResponseText NOT LIKE 'Result=OK%'
THEN
vErrorText := vResponseText;
END IF;
ELSE
vErrorText := 'HTTP status: '||vResponse.status_code||'-'||vResponse.reason_phrase;
END IF;
--
Utl_Http.end_response(vResponse);
--
IF vErrorText IS NOT NULL
THEN
RAISE_APPLICATION_ERROR(-20001, 'Sending SMS failed with '||vErrorText);
END IF;
END sendSMS;


Labels: , , , ,


« ... Read full posting ... »

Oracle 11g PL/SQL enhancements

Just read an interesting posting on Igor's Oracle Lab about the planned PL/SQL enhancements in Oracle 11g. I really like some of the planned features. Want to get the full story? Check out the presentation done by Tom Kyte.

Labels: , ,


« ... Read full posting ... »