I occasionally encounter examples where SELECT...INTO...FROM DUAL is used to call a function - e.g.:
SELECT some_function INTO a_variable FROM DUAL;
is used, instead of
a_variable := some_function;
My take on this is that it's not good practice because A) it makes it unclear that a function is being invoked, and B) it's inefficient in that it forces a transition from the PL/SQL engine to the SQL engine (perhaps less of an issue today).
Can anyone explain why this might have been done, e.g. was this necessary in early PL/SQL coding in order to invoke a function? The code I'm looking at may date from as early as Oracle 8.
Any insights appreciated.
This practice dates from before PLSQL and Oracle 7. As already mentioned assignment was possible (and of course Best Practice) in Oracle7.
Before Oracle 7 there were two widely used Tools that needed the use of Select ... into var from dual;
On the one hand there used to be an Oracle Tool called RPT, some kind of report generator. RPT could be used to create batch processes. It had two kinds of macros, that could be combined to achieve what we use PLSQL for today. My first Oracle job involved debugging PLSQL that was generated by a program that took RPT batches and converted them automatically to PLSQL. I threw away my only RPT handbook sometime shortly after 2000.
On the other hand there was Oracle Forms 2.x and its Menu component. Context switching in Oracle Menu was often done with a Select ... from dual; I still remember how proud I was when I discovered that an untractable Bug was caused by a total of 6 records in table Dual.
I am sorry to say that I can not proof any of this, but it is the time of year to think back to the old times and really fun to have the answer.
Related
I've seen lots of posts regarding the use of cursors in PL/SQL to return data to a calling application, but none of them touch on the issue I believe I'm having with this technique. I am fairly new to Oracle, but have extensive experience with MSSQL Server. In SQL Server, when building queries to be called by an application for returning data, I usually put the SELECT statement inside a stored proc with/without parameters, and let the stored proc execute the statement(s) and return the data automatically. I've learned that with PL/SQL, you must store the resulting dataset in a cursor and then consume the cursor.
We have a query that doesn't necessarily return huge amounts of rows (~5K - 10K rows), however the dataset is very wide as it's composed of 1400+ columns. Running the SQL query itself in SQL Developer returns results instantaneously. However, calling a procedure that opens a cursor for the same query takes 5+ minutes to finish.
CREATE OR REPLACE PROCEDURE PROCNAME(RESULTS OUT SYS_REFCURSOR)
AS
BEGIN
OPEN RESULTS FOR
<SELECT_query_with_1400+_columns>
...
END;
After doing some debugging to try to get to the root cause of the slowness, I'm leaning towards the cursor returning one row at a time very slowly. I can actually see this real-time by converting the proc code into a PL/SQL block and using DBMS_SQL.return_result(RESULTS) after the SELECT query. When running this, I can see each row show up in the Script output window in SQL Developer one at a time. If this is exactly how the cursor returns the data to the calling application, then I can definitely see how this is the bottleneck as it could take 5-10 minutes to finish returning all 5K-10K rows. If I remove columns from the SELECT query, the cursor displays all the rows much faster, so it does seem like the large amount of columns is an issue using a cursor.
Knowing that running the SQL query by itself returns instant results, how could I get this same performance out of a cursor? It doesn't seem like it's possible. Is the answer putting the embedded SQL in the application code and not using a procedure/cursor to return data in this scenario? We are using Oracle 12c in our environment.
Edit: Just want to address how I am testing performance using the regular SELECT query vs the PL/SQL block with cursor method:
SELECT (takes ~27 seconds to return ~6K rows):
SELECT <1400+_columns>
FROM <table_name>;
PL/SQL with cursor (takes ~5-10 minutes to return ~6K rows):
DECLARE RESULTS SYS_REFCURSOR;
BEGIN
OPEN RESULTS FOR
SELECT <1400+_columns>
FROM <table_name>;
DBMS_SQL.return_result(RESULTS);
END;
Some of the comments are referencing what happens in the console application once all the data is returned, but I am only speaking regarding the performance of the two methods described above within Oracle\SQL Developer. Hope this helps clarify the point I'm trying to convey.
You can run a SQL Monitor report for the two executions of the SQL; that will show you exactly where the time is being spent. I would also consider running the two approaches in separate snapshot intervals and checking into the output from an AWR Differences report and ADDM Compare Report; you'd probably be surprised at the amazing detail these comparison reports provide.
Also, even though > 255 columns in a table is a "no-no" according to Oracle as it will fragment your record across > 1 database blocks, thus increasing the IO time needed to retrieve the results, I suspect the differences in the two approaches that you are seeing is not an IO problem since in straight SQL you report fast result fetching all. Therefore, I suspect more of a memory problem. As you probably know, PL/SQL code will use the Program Global Area (PGA), so I would check the parameter pga_aggregate_target and bump it up to say 5 GB (just guessing). An ADDM report run for the interval when the code ran will tell you if the advisor recommends a change to that parameter.
Executive summary: PostgreSQL is amazing, but we are facing many issues at work due to the fact that it postpones many checks on PL/pgSQL code until runtime. Is there a way to make it more like Oracle's PL/SQL in this respect?
For example...
Try executing this in any Oracle DB:
create function foo return number as
begin
select a from dual;
return a;
end;
Oracle will immediately (i.e. at compile-time!) respond with:
[Error] ORA-00904: invalid identifier
Now try the semantically equivalent thing in PostgreSQL:
CREATE OR REPLACE FUNCTION public.foo ()
RETURNS integer AS
$body$
BEGIN
select a;
return a;
END;
$body$
LANGUAGE plpgsql;
You will see it - unfortunately! - execute fine ... No error is reported.
But when you then try to call this function (i.e. at runtime) you will get:
ERROR: column "a" does not exist
LINE 1: select a
Is there a way to force PostgreSQL to perform syntax analysis and checking at function definition time - not at run-time? We have tons of legacy PL/SQL code at work, which we are porting to PostgreSQL - but the lack of compile-time checks is very painful, forcing us to do manual work - i.e. writing code to test all code paths in all functions/procedures - that was otherwise automated in Oracle.
Yes, this is a known issue.
PL/pgSQL (like any other function, except on SQL) is a “black box” for the PostgreSQL, therefore it is not really possible to detect errors except in runtime.
You can do several things:
wrap your function calling SQL queries into BEGIN / COMMIT statements in order to have better control over errors;
add EXCEPTION blocks to your code to catch and track errors. Note, though, that this will affect function performance;
use plpgsql_check extension, developed by the Pavel Stěhule, who is one of the main contributors to PL/pgSQL development. I suppose eventually this extension will make it into the core of the PostgreSQL, but it'll take some time (now we're in 9.4beta3 state);
You might also look into this related question: postgresql syntax check without running the query
And it really looks like you're in a huge need of a unit testing framework.
Plpgsql language is designed without semantics checking at compile-time. I am not sure if this feature was an intention or a side effect of old plpgsql implementation, but over time we found some advantages to it (but also disadvantages as you mentioned).
Plus :
there are less issues with dependency between functions and other database objects. It's a simple solution to cyclic dependency problem. Deployment of plpgsql functions is easier, because you don't need to respect dependency.
Some patterns with temporary tables are possible using lazy dependency checking. It's necessary, because Postgres doesn't support global temporary tables.
Example:
BEGIN
CREATE TEMP TABLE xx(a int);
INSERT INTO xx VALUES(10); -- isn't possible with compile-time dependency checks
END;
Minus:
Compile-time deep checking is not possible (identifiers checking), although it's sometimes possible.
For some bigger projects a mix of solutions should be used:
regress and unit tests - it is fundamental, because some situations cannot be checked statically - dynamic SQL for example.
plpgsql_check - it is an external but supported project used by some bigger companies and bigger plpgsql users. It can enforce a static check of SQL identifiers validity. You can enforce this check by DDL triggers.
Is there any "best practice" on how to call a stored procedure from APEX instead of just using a simple DB-Link?
Calling PL/SQL Stored Procedures Within Oracle APEX
There's a great deal of detail involved with developing robust, maintainable and efficient solutions by paring PL/SQL stored procs with the Application Express web based frame work. Not knowing the current skill level of the author of the OP, I assume that the most helpful explanation is a simple example developed from scratch.
Getting Started: The APEX environment has a lot of tools that can get you started. If you don't already have an Oracle database environment with APEX installed, consider signing up for a free, hosted trial account through the APEX home page on Oracle.com.
Application Design Decisions
PL/SQL stored procedures are not necessary to develop applications on Oracle APEX, however they do supply a greater amount of flexibility and customization during the development process.
This example will use the popular schema object: EMP typically available as an optional part of each Oracle database installation. In case you don't have it, here is the DDL and DML source for building the example table:
The EMP Table (A Copy Aliased as: LAB01_SAMPLE_EMP)
CREATE TABLE "EMP"
( "EMPNO" NUMBER(4,0) NOT NULL ENABLE,
"ENAME" VARCHAR2(10),
"JOB" VARCHAR2(9),
"MGR" NUMBER(4,0),
"HIREDATE" DATE,
"SAL" NUMBER(7,2),
"COMM" NUMBER(7,2),
"DEPTNO" NUMBER(2,0),
PRIMARY KEY ("EMPNO") ENABLE
)
/
ALTER TABLE "EMP" ADD FOREIGN KEY ("MGR")
REFERENCES "EMP" ("EMPNO") ENABLE
/
If you would like some test data, this is what I had to work with:
BUILD a SQL-based DML update statement that will change the SAL (Salary) value for one employee at a time based on their ENAME.
WRAP the UPDATE DML statement into a reusable, compiled PL/SQL stored procedure. Include parameter arguments for the two data input values for "Name" and "Amount of Increase".
TEST the stored procedure and verify it works as required.
DESIGN and CODE an APEX Application Page which will:
(a) Show the current contents of the employee entity table.
(b) Accept input values to pass into the PL/SQL Stored Procedure.
(c) Utilize native APEX Error and Success message settings to provide more feedback on the outcome of the procedure call.
TEST the APEX page and verify it works as specified.
REVIEW the discussion and conclusions section at the end for additional comments and more tips to keep you moving on your own path to developing Oracle skills.
Programming a SQL DML Process
This is the initial example created to accomplish this task.
UPDATE LAB01_SAMPLE_EMP
SET SAL = SAL + 1250
WHERE ENAME = 'KING';
A quick revision reveals how we can parametrize the approach to make this statement
UPDATE LAB01_SAMPLE_EMP
SET SAL = SAL + p_salary_increase
WHERE ENAME = p_ename;
If you are not sure where to go next, this is where a lesson on "best-practices" is available thanks to APEX. Navigate to the OBJECT BROWSER and CREATE a Procedure Object. The application will walk through every step to set up a PL/SQL stored proc.
The Working PL/SQL Procedure Source Code:
After walking through the wizard setup, this is the cleaned-up stored procedure. There were some additional changes after debugging some compile-time error warnings:
create or replace procedure "PROC_UPDATE_SALARY"
(p_ename IN VARCHAR2, p_salary_increase IN VARCHAR2)
is
v_new_salary lab01_sample_emp.sal%TYPE;
begin
UPDATE LAB01_SAMPLE_EMP
SET SAL = SAL + p_salary_increase
WHERE ENAME = p_ename
RETURNING SAL INTO v_new_salary;
commit;
dbms_output.put_line('INCREASED SALARY FOR: ' || p_ename ||
' TO THE NEW AMOUNT OF: $ ' || to_char(v_new_salary));
end;
Best Practices, a Quick Aside and Discusssion: You just have to keep doing it... coding that is. There is just no way around it. Look for examples at work or in life and try your hand at developing schemas and designs to satisfy made-up but realistic requirements. For beginning developers, the PL/SQL stored procedure above may already show some "unfamiliar" or odd coding syntax and commands.
That is only the tip of what is possible out there. Coding style is also only a part of it as you get deeper into things, you may notice a few things:
ORGANIZATION is important. Learn quickly some conventions in naming and notation to use in the code. This will keep things organized and easy to find or reference elsewhere.
RECYCLE and REUSE means your code should be developed with reuse in mind. Common routines and processes should be bundled together to avoid redundancy.
ALWAYS TEST your work suggests that less frustration is found when initial, fundamental steps in your process or application have been carefully tested first before proceeding.
TESTING the Oracle PL/SQL Procedure
I used the built-in APEX scripting engine found in the SQL WORKSHOP section of the environment. Below is a screenshot of the output logs of my testing script.
Bringing it Together: Designing an APEX Application Page with a Procedure Call
Create or open up an APEX Application and start out by making a new page. There are system wizard processes that will help you get started if you haven't done this before.
Select the option to BUILD a FORM on top of a STORED PROCEDURE. There will be prompts for permission to build the page items needed for input parameters. Follow the wizard to completion to make sure all the dependent page design elements are included.
My near-finalized design is below:
There are a few extras added, such as the REPORT region to provide immediate visibility to the table and any applied changes to its data.
The Form in Action: Testing Data Input and Results
The SUCCESS alert message is a feature available for certain page elements to inform the user of any significant events conducted on the database.
Closing Comments and Discussion
The immediate answer to the question of the OP is YES, there are best practices. It is such a huge subject that the only realistic way of handling it is by walking through different examples to see the ways that these practices are "commonly" applied.
There were a few shortcuts involved in this solution (based on several assumptions) and it might be helpful to bring them up as a parting discussion on the possibility of revisiting this walk-through to make an improved, EMP-2.0 project.
The procedure works on the EMP table based on searches by ENAME. What is the REAL key of this table? Are there any risks involved with this approach- possibly with respect to larger data sets?
Most Oracle PL/SQL Objects used in production ready environments have some level of error trapping or exception handling through a PL/SQL EXCEPTION BLOCK. What kind of errors would you want to trap? How?
Don't underestimate the resources available within the APEX tool. There are lots of wizards that walk developers through the process of creating different, functioning modules of code. These automated guides provide solutions that can also be reverse-engineered to understand how the code was generated and also what general design approaches make compliant design patterns.
How do I debug a tsql Stored procedure. I have tried the following link.
http://msdn.microsoft.com/en-us/library/ms241871(v=vs.80).aspx
But I am unable to hit the break point. Is there a better way to debug. My environment is
Sql Express 2008, Visual Studio 2010
I have found the debugger in SQL Managment studio unreliable as it's so dependant on having the correct permissions on the db server which are not always available.
One alternate method I use is to convert the stored proc into a long query. I start by moving any parameteres to variable declarations and set their values. For examples the following
ALTER PROCEDURE [dbo].[USP_ConvertFinancials] (#EffectiveDate datetime, #UpdatedBy nvarchar(100))
AS
BEGIN
DECLARE #PreviousBusinessDay datetime
would become
DECLARE #Value int,
, #EffectiveDate datetime = '01-Jan-2011
, #UpdatedBy nvarchar(100) = 'System'
This allows me to run the queries within the stored procedure starting from the top. As I move down through the queries, I can check the values of variables by simply selecting them and rerunning the query from the top:
SELECT #Value
I can also comment out the INSERT portion of INSERT-SELECT statements to see what is being inserted into tables and table variables.
The bug in the stored proc usually becomes quite evident using this method. Once I get the query running correctly I can simply copy the code to my proc and recompile.
Good luck!
You can try out Sql Profiler, it does not allows a classical debugging like "break at this point" but gives you an information in great detail about what is going on on each step of a query/SP execution.
Unfortunately Microsoft does not provide it with Express Edition version of Sql Server.
BUT :) There is a good (relatively because it does not provide a lot of filtering criterias which exists in Microsoft's one) and free alternative - SQL Server 2005/2008 Express Profiler.
Debug a stored procedure.
check the logic whether it makes sense or not.
use break point to help find issues.
try to do the modular design as per complex process.
divide the task into multiple simple ones.
use a master stored procedure to take control on the top, and use several child stored procedures to do the job step by step.
As per the optimization, use execution plan, SS Profiler and DTA tools.
This question already has answers here:
Does Oracle have an equivalent of SQL Server's table variables?
(4 answers)
Closed 8 years ago.
I've recently started a new position as a developer and I'm having a bit of trouble with PL/SQL. I've used MS SQL for a number of years but I'm finding PL/SQL a bit trickier.
One of the things I used to do when writing functions and stored procedures in MS SQL was to put reoccuring result sets into a table variable so I wouldn't have to requery them throughout my procedure.
Something like this:
declare #badPeople table(recordPointer int)
insert into #badPeople
select BP_Record_Pointer
from People
where BP_Bad = 1
I'm looking at doing something similar in PL/SQL but I'm not quite sure how to get started. Any ideas if this is even possible?
declare
type t_number is table of number;
v_numbers t_number;
begin
select BP_Record_Pointer
bulk collect into v_numbers
from People
where BP_Bad = 1;
end;
This will create a nested table containing the values from your table. It's important to note that the table will go out-of-scope at the end of the anonymous block, so anything you want to do with it needs to be done inside that block.
In Oracle unlike MS SQL cursors are not considered the devil and something to avoid. So typically in Oracle you will make use of cursors much more often than you would in MS SQL. Of course if you can do it with only SQL and no cursor that is best, but don't be afraid to test and use cursors in Oracle. Get a good book on PL/SQL, this is a good one http://www.amazon.com/Oracle-PL-SQL-Programming-4th/dp/0596009771. The post by Gratzy is another option you can use. So get a good book that you can use to figure out when to use what. PL/SQL is a very rich environment compared to T-SQL. While it has more of a learning curve once you get over the initial curve it's a really easy and power full language. And on top of that it's a lot of fun.