Construct a Sql block using With Clause to improve the performance
I have got four diff parametrized cursor in my Pl/Sql Procedure. As the performance of the Procedure is very pathetic,so i have been asked to tune the Select statements used in those cursors.
So I am trying to use the With Clause in order to club all those four Select Statements.
I would appreciate if anybody can help me to construct the Sql Block using With Clause.
My DB version is..
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
Four Diff cursors are defined below.
CURSOR all_iss (
b_batch_end_date IN TIMESTAMP,
IS
SELECT isb.*
FROM IMPLMN_STEP_BREKPN isb
, ISSUE iss
WHERE isb.issue_id = iss.issue_id
AND iss.issue_status_id = 50738
AND ewo_no IN
(SELECT TO_CHAR(wo_no)
FROM MGO_PLANT_AUDIT
WHERE dml_status = 'U' OR dml_status = 'I')
UNION ALL
SELECT isb.*
FROM IMPLMN_STEP_BREKPN isb
, ISSUE iss
WHERE isb.issue_id = iss.issue_id
AND iss.issue_status_id = 50738
AND CAST (isb.last_updt_timstm AS TIMESTAMP) >=
b_batch_end_date;
CURSOR ewo_plant ( p_ewo_no IN IMPLMN_STEP_BREKPN.ewo_no%TYPE)
IS
SELECT DISTINCT wo_no ,
plant_code
FROM MGO_PLANT
WHERE TO_CHAR(wo_no) = p_ewo_no;
CURSOR iss_ewo_plnt (
p_issue_id IN IMPLMN_STEP_BREKPN.issue_id%TYPE ,
p_ewo_no IN IMPLMN_STEP_BREKPN.EWO_NO%TYPE,
p_plnt_code IN IMPLMN_STEP_BREKPN.PLT_FACLTY_ID%TYPE)
IS
SELECT *
FROM IMPLMN_STEP_BREKPN
WHERE issue_id = p_issue_id
AND ewo_no = p_ewo_no
AND
(plt_faclty_id = p_plnt_code
OR
plt_faclty_id IS NULL);
CURSOR iss_ewo_plnt_count (
p_issue_id IN IMPLMN_STEP_BREKPN.issue_id%TYPE ,
p_ewo_no IN IMPLMN_STEP_BREKPN.EWO_NO%TYPE,
p_plnt_code IN IMPLMN_STEP_BREKPN.PLT_FACLTY_ID%TYPE)
IS
SELECT COUNT(*)
FROM IMPLMN_STEP_BREKPN
WHERE issue_id = p_issue_id
AND ewo_no = p_ewo_no
AND
(plt_faclty_id = p_plnt_code
OR
plt_faclty_id IS NULL);
Not tested. Some thing like below. i just made the queries as tables and given name as a,b,c and substituted columns for the parameters used in the 2nd cursor and third cursor. Try like this.
CURSOR all_iss (
b_batch_end_date IN TIMESTAMP,
IS
select a.*,b.*,c.* from
( SELECT isb.*
FROM IMPLMN_STEP_BREKPN isb
, ISSUE iss
WHERE isb.issue_id = iss.issue_id
AND iss.issue_status_id = 50738
AND ewo_no IN
(SELECT TO_CHAR(wo_no)
FROM MGO_PLANT_AUDIT
WHERE dml_status = 'U' OR dml_status = 'I')
UNION ALL
SELECT isb.*
FROM IMPLMN_STEP_BREKPN isb
, ISSUE iss
WHERE isb.issue_id = iss.issue_id
AND iss.issue_status_id = 50738
AND CAST (isb.last_updt_timstm AS TIMESTAMP) >=
b_batch_end_date) a,
( SELECT DISTINCT wo_no ,
plant_code
FROM MGO_PLANT
WHERE TO_CHAR(wo_no) = p_ewo_no) b,
( SELECT *
FROM IMPLMN_STEP_BREKPN
WHERE issue_id = p_issue_id
AND ewo_no = p_ewo_no
plt_faclty_id IS NULL) c
where b.wo_no = c.ewo_no and
c.issue_id = a.issue_id ;
vinodh
Edited by: Vinodh2 on Jul 11, 2010 12:03 PM
Similar Messages
-
Hi,
I am looking for inputs in tuning stored procedure using sql server 2008. l am new to performance tuning in sql,plsql and oracle. currently facing issue in stored procedure - need to increase the performance by code optmization/filtering the records using where clause in larger table., the requirement is Stored procedure generate Audit Report which is accessed by approx. 10 Admin Users typically 2-3 times a day by each Admin users.
It has got CTE ( common table expression ) which is referred 2 time within SP. This CTE is very big and fetches records from several tables without where clause. This causes several records to be fetched from DB and then needed processing. This stored procedure is running in pre prod server which has 6gb of memory and built on virtual server and the same proc ran good in prod server which has 64gb of ram with physical server (40sec). and the execution time in pre prod is 1min 9seconds which needs to be reduced upto 10secs or so will be the solution. and also the exec time differs from time to time. sometimes it is 50sec and sometimes 1min 9seconds..
Pl provide what is the best option/practise to use where clause to filter the records and tool to be used to tune the procedure like execution plan, sql profiler?? I am using toad for sqlserver 5.7. Here I see execution plan tab available while running the SP. but when i run it throws an error. Pl help and provide inputs.
Thanks,
VijiYou've asked a SQL Server question in an Oracle forum. I'm expecting that this will get locked momentarily when a moderator drops by.
Microsoft has its own forums for SQL Server, you'll have more luck over there. When you do go there, however, you'll almost certainly get more help if you can pare down the problem (or at least better explain what your code is doing). Very few people want to read hundreds of lines of code, guess what's it's supposed to do, guess what is slow, and then guess at how to improve things. Posting query plans, the results of profiling, cutting out any code that is unnecessary to the performance problem, etc. will get you much better answers.
Justin -
Using WITH clause in Pro*Cobol
Hi!
I am trying to improve the performance of a query by introducing WITH clause.
The query is in Pro*Cobol Release 9.2.0.6.0 - Production.
I got compilation error
WITH DPTCOST AS (
...............1
PCB-S-00400, Encountered the symbol "DPTCOST" when expecting one of the following:
END-EXEC
....continued
So I wonder if we could use that clause at all with Pro*Cobol
Here is the excerp of the code
EXEC SQL
DECLARE INPUT_ACTUAL CURSOR FOR
WITH DPTCOST AS (
SELECT /*+ rule */
A.CODE_COMBINATION_ID,
A.SEGMENT1, A.SEGMENT2, A.SEGMENT3,
A.SEGMENT6,
D.COSTING, D.PROCESS,
D.MTL_CODE, D.FACTOR
FROM
GL_CODE_COMBINATION A,
ALCGL_DEPARTMENT_COSTINGS D
WHERE
A.TEMPLATE_ID IS NULL
AND A.SUMMARY_FLAG <> 'Y'
AND A.SEGMENT1 = D.PLANT_NUMBER
AND A.SEGMENT3 <> '6999001'
AND A.SEGMENT3 <> '6999002'
AND SUBSTR(A.SEGMENT2,4,3) = D.DEPARTMENT
AND D.ACTUAL_FLAG = 'A'
) ... continuedMaterialized views are basically stored query results. They offer advanced functionality like query rewrite, refresh on commit, and more;
http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_6002.htm
Unlike a view, they actually store the results of the query - not just the query;
SQL> create table t (cid number primary key)
Table created.
SQL> insert into t select object_id from dba_objects where object_id is not null
12791 rows created.
SQL> create materialized view mv
as select * from t
Snapshot created.
SQL> select object_name, object_type from user_objects where object_name ='MV'
OBJECT_NAME OBJECT_TYPE
MV TABLE
MV MATERIALIZED VIEW
2 rows selected.
SQL> select segment_name, bytes from user_segments where segment_name in ('T', 'MV')
SEGMENT_NAME BYTES
T 196608
MV 196608
2 rows selected.Temporary tables are simply tables that are created then dropped. GLOBAL TEMPORARY TABLES have the advantage (or disadvantage) of only existing until commit or the end of the session. They results are visible to the user that inserted the data - but only temporarily;
http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7002.htm#sthref7483 -
'Missing select' error for update statement using WITH clause
Hi,
I am getting the below error for update statement using WITH clause
SQL Error: ORA-00928: missing SELECT keyword
UPDATE A
set A.col1 = 'val1'
where
A.col2 IN (
WITH D AS
SELECT col2 FROM
(SELECT col2, MIN(datecol) col3 FROM DS
WHERE <conditions>
GROUP BY PATIENT) D2
WHERE
<conditions on A.col4 and D2.col3>Hi,
The format of a query using WITH is:
WITH d AS
SELECT ... -- sub_query
SELECT ... -- main query
You don't have a main query. The keyword FROM has to come immediately after the right ')' that ends the last WITH clause sub-query.
That explains the problem based on what you posted. I can't tell if the real problem is in the conditions that you didn't post.
I hope this answers your question.
If not, post a complete test script that people can run to re-create the problem and test their ideas. Include a little sample data (CREATE TABLE and INSERT statements, relevant columns only) for all the tables involved, and the results you want from that data.
In the case of a DML operation (such as UPDATE) the sample data should show what the tables are like before the DML, and the results will be the contents of the changed table(s) after the DML.
Explain, using specific examples, how you get those results from that data.
Always say what version of Oracle you're using (e.g. 11.2.0.2.0).
See the forum FAQ: https://forums.oracle.com/message/9362002 -
I have an update statement that is using the same suquery twice.
I am not usre if WITh clause be used in update statements?
Is there a way the below statement can be modified to use WITH clause?
UPDATE EMP_TRACKING_LIST L
SET ACTIVE_FLAG = DECODE((SELECT COUNT(*)
FROM EMP_TRACKING_LIST L2
WHERE L.NAME = L2.NAME AND
L.EMP_CODE = L2.EMP_CODE AND
L2.EMP_FLAG = 'Y'), 0, 'N', 'Y')
WHERE ACTIVE_FLAG != DECODE((SELECT COUNT(*)
FROM EMP_TRACKING_LIST L2
WHERE L.NAME = L2.NAME AND
L.EMP_CODE = L2.EMP_CODE AND
L2.EMP_ACTIVE_FLAG = 'Y'), 0, 'N', 'Y')
OR EMP_ACTIVE_FLAG IS NULL;
I would really appreciate your input
Edited by: user10937534 on Sep 2, 2009 4:47 PMHi,
WITH comes immediately before SELECT, not before UPDATE.
To use WITH in an UPDATE statement, you would say something like:
UPDATE EMP_TRACKING_LIST L
SET ACTIVE_FLAG =
WITH sub_q AS
SELECT ...
SELECT ...
FROM sub_q ...
;I don't think there's any way to use values from the sub-query in the WHERE clause of the UPDATE statement itself; MERGE is a much better bet for eliminating redundancy there.
Sorry, I'm not at a database now, so I can test anything. -
Executing a PL/SQL block (using Toplink)
I have a scenario where I need to execute some fairly complex PL/SQL blocks. As a tester, I am attempting to execute the following simple block:
declare val NUMBER := 1; begin val := 2; end;
Both wrapping this in an SQLCall, or a DataReadQuery give the following exception. What is the best way to execute a PL/SQL block using Toplink?
Local Exception Stack:
Exception [TOPLINK-4002] (Oracle TopLink - 10g Release 3 (10.1.3.0.0) (Build 060118)): oracle.toplink.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: ORA-00900: invalid SQL statement
Error Code: 900
Call: declare val NUMBER := 1; begin val := 2; end;
Query:DataReadQuery()
at oracle.toplink.exceptions.DatabaseException.sqlException(DatabaseException.java:290)
at oracle.toplink.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:570)
at oracle.toplink.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:442)
at oracle.toplink.threetier.ServerSession.executeCall(ServerSession.java:453)
at oracle.toplink.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:117)
at oracle.toplink.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:103)
at oracle.toplink.internal.queryframework.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:174)
at oracle.toplink.internal.queryframework.DatasourceCallQueryMechanism.executeSelect(DatasourceCallQueryMechanism.java:156)
at oracle.toplink.queryframework.DataReadQuery.executeNonCursor(DataReadQuery.java:118)
at oracle.toplink.queryframework.DataReadQuery.executeDatabaseQuery(DataReadQuery.java:110)
at oracle.toplink.queryframework.DatabaseQuery.execute(DatabaseQuery.java:603)
at oracle.toplink.queryframework.DataReadQuery.execute(DataReadQuery.java:96)
at oracle.toplink.publicinterface.Session.internalExecuteQuery(Session.java:2062)
at oracle.toplink.publicinterface.Session.executeQuery(Session.java:981)
at oracle.toplink.publicinterface.Session.executeQuery(Session.java:938)Could you try the following:
Session s = ...
DataModifyQuery dmq = new DataModifyQuery();
SQLCall sqlCall = new SQLCall();
sqlCall.setQueryString(
"declare\n" +
" val NUMBER := 1;\n" +
"begin\n" +
" val := 2;\n" +
"end;");
sqlCall.setQuery(dmq);
dmq.setCall(sqlCall);
s.executeQuery(dmq); -
I cannot make these directions work
I downloaded media on Overdrive MEdia on my PC
I have the overdrive media ap on my I pod touch 4g
this media is suppossed to be compatible w/I pd touch
Notes on Transferring OverDrive MP3 Audiobooks…
Most MP3 capable devices should play OverDrive MP3 Audiobooks.
If you intend to transfer OverDrive MP3 Audiobooks to an Apple® device, note the following…
iTunes® v9.0.2 (or newer) is required.
The Apple device must be formatted for use with Microsoft® Windows®.
The iTunes setting 'Manually manage music…' must be enabled for the device before you can complete the transfer. Adjust this setting in iTunes as follows…
Connect the iPod® to your computer.
If it does not launch automatically, open iTunes v9.0.2 (or newer).
In iTunes, locate the device in the left vertical navigation panel (under heading 'DEVICES'), and click the device.
The 'Summary' screen is displayed.
Place a checkmark next to 'Manually manage music…'.
Click the 'Apply' button.
The iTunes 'Summary' screen refreshes, and the changes are saved.
If desired, close iTunes.
Note that if an Apple device is connected to your computer, you can choose to simultaneously transfer a title to the iTunes Library and the Apple device. If you wish to only transfer a title to the iTunes Library, you must first disconnect the Apple deviceRecovering your iTunes library from your iPod or iOS device: Apple Support Communities
Also you said " I want to add them to my iCloud, and also back to my computer. " Note that unless subscribe to iTunes match, only iTunes purchases are stored in iCloud.
Also,
You can redownload most iTunes purchases by:
Downloading past purchases from the App Store, iBookstore, and iTunes Store -
My Iphone 5s shows "No Service" in the specific network area, but if the same sim card is used with other mobiles in the same network area, it shows good network.. i did restore,change sim card, reset all the settings but still not working... please help me..
Please do not double post a subject. Iphone 5S I answered your other thread.
-
I have the CANON REBEL T5 1200D, and when i connect it to my mac which is 10.10 the new OS X YOSEMITE it says that it "Cannot be used with this version of the operating system" why does it say that if my camera is listed under the supported digital cameras for OS X YOSEMITE?
Put simply, the minimum system requirements for iTunes have changed. You need a Mac running at least OS X 10.6.8.
It's best you look online to see if your model of Mac can be upgraded to at least 10.6.8 "Snow Leopard". It should still be possible to order a copy of Snow Leopard if so. -
I have a 500 gig time capsule. I have used with a Macbook. The Macbook has a 500 gig hard drive which is about 3/4 full. Now we just purchased a new MacBook pro with a 1 TB hard drive. Do I need to buy a larger Time Capsule?
Do I need to buy a larger Time Capsule?
Probably yes. You might be able to get the full backup of the new MacBook Pro on the Time Capsule, but it will not be long before the Time Capsule is out of space.
Better to add a new Time Capsule and backup the new MacBook Pro to the new Time Capsule, and keep the old MacBook backing up to the old Time Capsule.
If you do not want to add a new Time Capsule, another option would be to erase the Time Capsule disk and start over again with new backups of both Macs and move forward. -
Need help in improving the performance for the sql query
Thanks in advance for helping me.
I was trying to improve the performance of the below query. I tried the following methods used merge instead of update, used bulk collect / Forall update, used ordered hint, created a temp table and upadated the target table using the same. The methods which I used did not improve any performance. The data count which is updated in the target table is 2 million records and the target table has 15 million records.
Any suggestions or solutions for improving performance are appreciated
SQL query:
update targettable tt
set mnop = 'G',
where ( x,y,z ) in
select a.x, a.y,a.z
from table1 a
where (a.x, a.y,a.z) not in (
select b.x,b.y,b.z
from table2 b
where 'O' = b.defg
and mnop = 'P'
and hijkl = 'UVW';987981 wrote:
I was trying to improve the performance of the below query. I tried the following methods used merge instead of update, used bulk collect / Forall update, used ordered hint, created a temp table and upadated the target table using the same. The methods which I used did not improve any performance. And that meant what? Surely if you spend all that time and effort to try various approaches, it should mean something? Failures are as important teachers as successes. You need to learn from failures too. :-)
The data count which is updated in the target table is 2 million records and the target table has 15 million records.Tables have rows btw, not records. Database people tend to get upset when rows are called records, as records exist in files and a database is not a mere collection of records and files.
The failure to find a single faster method with the approaches you tried, points to that you do not know what the actual performance problem is. And without knowing the problem, you still went ahead, guns blazing.
The very first step in dealing with any software engineering problem, is to identify the problem. Seeing the symptoms (slow performance) is still a long way from problem identification.
Part of identifying the performance problem, is understanding the workload. Just what does the code task the database to do?
From your comments, it needs to find 2 million rows from 15 million rows. Change these rows. And then write 2 million rows back to disk.
That is not a small workload. Simple example. Let's say that the 2 million row find is 1ms/row and the 2 million row write is also 1ms/row. This means a 66 minute workload. Due to the number of rows, an increase in time/row either way, will potentially have 2 million fold impact.
So where is the performance problem? Time spend finding the 2 million rows (where other tables need to be read, indexes used, etc)? Time spend writing the 2 million rows (where triggers and indexes need to be fired and maintained)? Both? -
How can I Improve the Performance using Global Temo Tables ??
Hi,
Can anyone tell me , How can i make use of Global Temporary Tables to improve the Performance.
I have few sample scripts ,
Say i have the View based on some Complex query like ,
CREATE OR REPLACE VIEW Profile_values_view AS
SELECT d.Profile_option_name, d.Profile_option_id, Profile_option_value,
u.User_name, Level_id, Level_code
FROM Profile_definitions d, Profile_values v, Profile_users u
WHERE d.Profile_option_id = v.Profile_option_id
AND ((Level_code = 'USER' AND Level_id = U.User_id) OR
(Level_code = 'DEPARTMENT' AND Level_id = U.Department_id) OR
(Level_code = 'SITE'))
AND NOT EXISTS (SELECT 1 FROM PROFILE_VALUES P
WHERE P.PROFILE_OPTION_ID = V.PROFILE_OPTION_ID
AND ((Level_code = 'USER' AND
level_id = u.User_id) OR
(Level_code = 'DEPARTMENT' AND
level_id = u.Department_id) OR
(Level_code = 'SITE'))
AND INSTR('USERDEPARTMENTSITE', v.Level_code) >
INSTR('USERDEPARTMENTSITE', p.Level_code));
Now i have created the Global temp Table as ,
CREATE GLOBAL TEMPORARY TABLE Profile_values_temp
Profile_option_name VARCHAR(60) NOT NULL,
Profile_option_id NUMBER(4) NOT NULL,
Profile_option_value VARCHAR2(20) NOT NULL,
Level_code VARCHAR2(10) ,
Level_id NUMBER(4) ,
CONSTRAINT Profile_values_temp_pk
PRIMARY KEY (Profile_option_id)
) ON COMMIT PRESERVE ROWS ORGANIZATION INDEX;
Now I am Inserting the Records into Temp table as
INSERT INTO Profile_values_temp
(Profile_option_name, Profile_option_id, Profile_option_value,
Level_code, Level_id)
SELECT Profile_option_name, Profile_option_id, Profile_option_value,
Level_code, Level_id
FROM Profile_values_view;
COMMIT;
Now what my doubt is, when do i need to execute the Insert Statement.
Say , if the View returns few millions of records , then loading such a data into Global Temporary table takes lot of time.
Then what is the use of Global Temporary tables and how can i improve the Performance using the same.
RajThanks for the responce ,
There are 2 to 3 complex views in our database, and there always be more than 5000+ users will be workinf on the application and is OLTP application. Those complex views are killing the application performance.
I what i felt was, if i create the Global Temporary tables for thow views and will be able to load the one third million of records returned by the views in to cache and can improve the application performance.
I have created the Global Temporary tables for 2 views with the option On Commit Preserve , But after am inserting the records into the Temp table and when i Issue the commit statement, the Temp table is getting Cleared.
I really got surpised of this behaviour as i know that with the Option On Commit Preserve , the rows should retain in the Temp Table, Instead , it's getting cleared.
Pelase suggest , what to do ??
Raj -
I am using the sql with following construct , the explain plan doesn't show that index on col1 of tab1 (used in with clause) as used- it just shows a full table access of a view (system) - result set of query in with clause.
1. Is it that oracle will not use that index or it doesn't show up
2. If so then is it good to have that table in join of all the three sqls that i am doing union - atleast in that case the index on col1 gets used (per explain plan).
with sql1 ( select * from tab1 where col1 = 'y')
select col_gen
from tab2 a, sql1 b
where a.col3 = b.col3
union
select col_gen
from tab3 a, sql1 b
where a.col3 = b.col4
Union
select col_gen
from tab4 a, sql1 b
where a.col3 = b.col4WITH tab1 AS ( SELECT * FROM tab12 WHERE SESSION_ID = '12')
SELECT DISTINCT b.unit_key unit_key ,NULL colabc1_KEY ,NULL colabc3_KEY,a.col3_ID
FROM tab1_col31_MAP a, tab1 b
WHERE a.unit_id = b.unit_id
UNION
SELECT DISTINCT NULL unit_key ,b.colabc1_KEY colabc1_KEY,NULL colabc3_KEY,a.col3_ID
FROM tab2_col32_MAP a,tab1 b
WHERE a.colabc1_id = b.colabc1_id
UNION
SELECT DISTINCT NULL unit_key,NULL colabc2_KEY,b.colabc3_KEY colabc3_KEY,a.col3_ID
FROM tab1_col33 a, tab1 b
WHERE a.colabc3_id = b.colabc3_id
Operation Object Name Rows Bytes Cost Object Node In/Out PStart PStop
SELECT STATEMENT Optimizer Mode=CHOOSE
RECURSIVE EXECUTION SYS_LE_2_0
TEMP TABLE TRANSFORMATION
SORT UNIQUE
UNION-ALL
NESTED LOOPS
VIEW
TABLE ACCESS FULL SYS_TEMP_0FD9D6603_53EE226
INDEX RANGE SCAN SYS_C00133240
NESTED LOOPS
VIEW
TABLE ACCESS FULL SYS_TEMP_0FD9D6603_53EE226
INDEX RANGE SCAN SYS_C00133205
NESTED LOOPS
VIEW
TABLE ACCESS FULL SYS_TEMP_0FD9D6603_53EE226
INDEX RANGE SCAN SYS_C00133202
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SELECT * FROM tab12 WHERE SESSION_ID = '12'
Operation Object Name Rows Bytes Cost Object Node In/Out PStart PStop
SELECT STATEMENT Optimizer Mode=CHOOSE
TABLE ACCESS BY INDEX ROWID tab12
INDEX RANGE SCAN IDX
Will the temp table transformation use the index used in the query above (ie. IDX) -
Accepting user input and executing a PL/SQL block using it
Hi All,
I am working on a requirement wherein I have to accept values from the user for the various arguments to be supplied to a PL/SQL block and then execute it using these values. For now, I am using the following logic:
PROMPT Enter value for the Category
ACCEPT cCategory CHAR PROMPT 'Category:'
DECLARE
cCategry CHAR(1) := '&cCategory';
BEGIN
DBMS_OUTPUT.PUT_LINE('The value of the Category as entered by you is' || cCategory);
END;
PROMPT Press y if you want to proceed with the current values, or press n if you want to re-enter the values
ACCEPT cChoice CHAR Prompt 'Enter y or n:'
DECLARE
cCategry CHAR(1) := '&cCategory';
sErrorCd VARCHAR2(256);
sErrorDsc VARCHAR2(256);
BEGIN
IF '&cChoice' = 'y'
THEN
DBMS_OUTPUT.PUT_LINE('Starting with the process to execute the stored proc');
--- schema1.package1.sp1(cCategry, sErrorCd, sErrorDsc);
--- DBMS_OUTPUT.PUT_LINE('Error Code :' || sErrorCd);
--- DBMS_OUTPUT.PUT_LINE(' Error Description :' || sErrorDsc);
ELSIF '&cChoice' = 'n'
THEN
Now I want that the proc again start executing in the loop from the 1st line i.e. PROMPT Enter value for the Category. However i see that this is not possible to do that PROMPT statements and accepting user inputs execute only on the SQL prompt and not inside a PL/SQL block.
Is there an alternate method to establish this?
Thanks in advance.Hi,
You can write a genric procedure to achive the desired output. Pass 'Y' or 'N' in the procedure.
Call that procedure in simple pl/sql block during runtime using substituton operator.
For ex
create or replace procedure p1(category_in in varchar2)
IS
BEGIN
if (category_in='Y')
then
prcdr1()
/** Write your logic here ***/
elsif(category_in='N') then
prcdr2()
/** write your logic here***/
end if;
exception
/***write the exception logic ***/
end p1;
Begin
p1('&cat');
end;Regards,
Achyut K
Edited by: Achyut K on Aug 6, 2010 5:20 AM -
How to rewrite dynamic SQL built using IF clauses, as static SQL?
Hi folks
I have some Dynamic SQL that I would like to rewrite as static.
The original PL/SQL code contains a number of IF clauses that I would normally replace with CASE statements in the static code, but I am wondering if I'm doing it the best way as although it works, I am not that happy with it for reasons described below.
[Please excuse any remaining syntax errors, I have tried to reduce them but we have no Oracle on our internet network and I can't CutnPaste from the dev network.]
So...
An example of what I would normally do.
A silly example, I admit, but it's just for demo.
Original Dynamic Code:
PROCEDURE GET_EMP_NAMES(p_job_title IN VARCHAR2 := NULL
,p_car_class IN NUMBER := NULL
,p_REF_CURSOR OUT CURVAR)
Purpose: Provide names of all employees. But if MANAGERS only is requested,
then limit the result set to those employees with the car class specified.
Fields in table emp: first_name, fam_name, car_class(NUMBER)
AS
v_str VARCHAR2(1000);
BEGIN
v_str := 'select e.first_name, e.fam_name FROM emp e WHERE 1=1 ';
IF p_job_title = 'MANAGER' and p_car_class IS NOT NULL THEN
v_str := v_str || ' AND e.car_class = ' || p_car_class;
END IF;
OPEN p_REF_CURSOR FOR v_str;
END;My usual rewrite:
BEGIN
OPEN p_REF_CURSOR FOR
SELECT e.first_name, e.fam_name
FROM emp e
WHERE e.car_class =
CASE WHEN p_job_title = 'MANAGER' AND p_car_class IS NOT NULL
THEN p_car_class
ELSE e.car_class
END;
END;My problem with this is that some employees may have an e.car_class of NULL.
In this case the WHERE clause will evaluate to NULL = NULL, and so they will not be included in the result set.
So I usually defend with NVL() and some fictive constant for the NVL result, ie:
AS
k_dummy_val CONSTANT NUMBER(20) := 56394739465639473946;
BEGIN
OPEN p_REF_CURSOR FOR
SELECT e.first_name, e.fam_name
FROM emp e
WHERE NVL(e.car_class,k_dummy_val) =
CASE WHEN p_job_title = 'MANAGER' AND p_car_class IS NOT NULL
THEN p_car_class
ELSE NVL(e.car_class,k_dummy_val)
END;
END;But now I have had to decide what to use for k_dummy_val. I need to choose some fictive number that is not and will not EVER be used as a car class. This is a problem as I do not know this.
So this makes me think that my technique is incorrect.
Do you have any suggestions?
Many thanks
Assaf
Edited by: user5245441 on 03:55 24/04/2011Hi,
Assaf wrote:
... if I were to do the following then it would be a mess, right? Barckets are needed and if I have many such conditions and make a mistake with the brackets, then... :(Brackets may be needed, but they're a good idea even if they are not needed.
WHERE p_job_title != 'MANAGER'
OR 'X' || TO_CHAR (car_class)
= 'X' || TO_CHAR (p_car_class)
AND p_yet_another_param != 'SOMETHING ELSE'
OR 'X' || TO_CHAR (another_field)
= 'X' || TO_CHAR (p_another_param)What do you think?Using parenetheses, that would be:
WHERE ( p_job_title != 'MANAGER'
OR 'X' || TO_CHAR (car_class)
= 'X' || TO_CHAR (p_car_class)
AND ( p_yet_another_param != 'SOMETHING ELSE'
OR 'X' || TO_CHAR (another_field)
= 'X' || TO_CHAR (p_another_param)
)I find this clearer than CASE expressions, but I won't be maintaining your code.
This is one place where implicit conversions won't hurt you. Both operands to || have to be strings. If you use a NUMBER as an operand to ||, then it will be implicitly converted to a string. Usually, it's better to make this clear by using TO_CHAR, and converting the NUMBER to a string explicitly, but in this case you might gain clarity by not using TO_CHAR.
Put comments in your code where you think they'll help someone to read and understand it.
WHERE
-- p_car_class only applies to MANAGERs
( p_job_title != 'MANAGER'
OR 'X' || car_class
= 'X' || p_car_class
AND ( p_yet_another_param != 'SOMETHING ELSE'
OR 'X' || another_field
= 'X' || p_another_param
... I avoid dynamic whenever possible, leaving it for use only in situations where things such as Table Names are unknown at compile time. I find it complex and error prone, and especially difficult for another developer to support at a later date.I agree. I agree especially with being concerned about the developer who has to modify or debug the code in the future, regardless of whether it's you or another.
Maybe you are looking for
-
Can anyone help with this Error?
An internal error has occurred: *** -[__NSArrayM objectAtIndex:]: index 9 beyond bounds [0 .. 8] when trying to export photos to an email folder on my desktop thanks JD
-
I use iTunes 12. When I share the iTunes library (on my iMac) I frequently lose connection when my iPhone plays a playlist from the iMac iTunes library. Can you help me find a solution?
-
Maintain JCO destination button is disabled
I am getting the following error when trying to log in to MSS: "com.sap.tc.webdynpro.services.exceptions.WDRuntimeE xception: Failed to resolve JCO destination name 'SAP_R3_SelfServiceGenerics_MetaData' in the SLD. No such JCO destination is defined
-
WHEN IAM DOING INVOICE.I AM GETTING ERROR THAT NO ACCOUTING DOCUMENT GENARATED. PLEASE SOLVE THIS PROBLEM.
-
Unwanted websites open in a new window
Unwanted websites pop up when I click on anything in Firefox (my bookmarks, links, or just anywhere on the screen). Usually these websites are some random advertising things. I have this problem since 3 days and it happens very often. I scanned my co