schemes of same bind variable
I used same set of values when the following SQL execution, but it seems that the plans are changed, can someone explain the cause of this behavior.
BANNER CON_ID
-------------------------------------------------------------------------------- ----------
Database Oracle 12 c Enterprise Edition Release 12.1.0.1.0 - 64 bit Production 0
PL/SQL Release 12.1.0.1.0 - Production 0
CORE 12.1.0.1.0 Production 0
AMT for Linux: Version 12.1.0.1.0 - Production 0
NLSRTL Version 12.1.0.1.0 - Production 0
Select table_name, column_name, histogram, num_distinct dba_tab_col_statistics where table_name = 'TEMP' and column_name = 'FILE_ID ';
TABLE_NAME COLUMN_NAME NUM_DISTINCT HISTOGRAM
-------------------- -------------------- ------------ ---------------
FILE_ID TEMP 5 FREQUENCY
TABLE_NAME COLUMN_NAME ENDPOINT_VALUE
-------------------- -------------------- --------------
FILE_ID TEMP 1
FILE_ID TEMP 3
FILE_ID TEMP 4
FILE_ID TEMP 6
FILE_ID TEMP 8
TABLE_NAME SAMPLE_SIZE NUM_ROWS
-------------------- ----------- ----------
9569280 9569280 TEMP
Connected.
SQL > variable x number;
SQL > set line 120
SQL > set autotrace on explain
SQL > col for a20 owner
SQL > exec: x: = 4
PL/SQL procedure successfully completed.
SQL > select owner, count (*) temp where file_id = 4 groups by order of owner by 2;
OWNER COUNT (*)
-------------------- ----------
SYS 109568
Execution plan
----------------------------------------------------------
Hash value of plan: 3296224485
----------------------------------------------------------------------------------------------
| ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 16. 144. 2794 (1) | 00:00:01 |
| 1. SORT ORDER BY | | 16. 144. 2794 (1) | 00:00:01 |
| 2. HASH GROUP BY. | 16. 144. 2794 (1) | 00:00:01 |
| 3. TABLE ACCESS BY ROWID INDEX BATCH | TEMP | 109K | 963K | 2790 (1) | 00:00:01 |
|* 4 | INDEX RANGE SCAN | IDX | 114K | | 331 (1) | 00:00:01 |
----------------------------------------------------------------------------------------------
Information of predicates (identified by the operation identity card):
---------------------------------------------------
4 - access ("FILE_ID" = 4)
SQL > select owner, count (*) temp where file_id =: x group by order of owner by 2.
OWNER COUNT (*)
-------------------- ----------
SYS 109568
Execution plan
----------------------------------------------------------
Hash value of plan: 386304853
----------------------------------------------------------------------------
| ID | Operation | Name | Lines | Bytes | Cost (% CPU). Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 16. 144. 44628 (1) | 00:00:02 |
| 1. SORT ORDER BY | | 16. 144. 44628 (1) | 00:00:02 |
| 2. HASH GROUP BY. | 16. 144. 44628 (1) | 00:00:02 |
|* 3 | TABLE ACCESS FULL | TEMP | 1913 K | 16 M | 44538 (1) | 00:00:02 |
----------------------------------------------------------------------------
Information of predicates (identified by the operation identity card):
---------------------------------------------------
3 filter ('FILE_ID' = TO_NUMBER (:X))
Hello
A few notes:
(1) SQL > set autotrace on explain
(2) from running with the literal:
Information of predicates (identified by the operation identity card):
---------------------------------------------------
4 - access ("FILE_ID" = 4)
(3) from running with bind:
Information of predicates (identified by the operation identity card):
---------------------------------------------------
3 - filter ("FILE_ID" =TO_NUMBER(:X))
See how you have a to_number() in there? It of the autotrace behavior and would explain the difference in the execution plan.
You can find more information search on the web, but a good starting point is here for information additional (Jonathan Lewis - Oracle Notepad):
AutoTrace tip | Notebook of the Oracle
Kind regards
Mark
Tags: Database
Similar Questions
-
Bind Variables and using the keyword
In my dynamic SQL, I use the same variable in several places in my query. Is there a way to avoid rewriting the same value multiple times in the list of arguments to bind? It is something like that - only pseudo code.
Is there a way to avoid having to rewrite the same argument three times bind variable as the value is the same?DECLARE tSQL VARCHAR2(99) pVal INT := 2; BEGIN tSQL := 'SELECT * ' || ' FROM dual ' || ' WHERE col1 =: iVal ' || ' AND col2 IN (SELECT col2 ' || ' FROM dual ' || ' WHERE col1 =: iVal) ' || ' UNION ' || ' SELECT * ' || ' FROM dual ' || ' WHERE col1 =: iVal'; EXECUTE IMMEDIATE tSQL USING pVal, pVal, pVal; -- Is there a way to avoid having to rewrite the same bind variable argument three times since the value is the same? END;
Etbin wrote:
http://docs.Oracle.com/CD/E11882_01/AppDev.112/e25519/dynamic.htm#BHCHIHEJ says:
Placeholders are associated with bind variable in the USING clause of position, and not by name.Concerning
Etbin
The exception to this rule is if the SQL statement is an anonymous block or a call statement. In this case, the repetition of the names of the placeholder is significant.
http://docs.Oracle.com/CD/E11882_01/AppDev.112/e25519/dynamic.htm#CHDFHEAG
For example, the following will fail with ORA-01008: not all variables
declare v_cnt number; begin execute immediate 'select count(*) from dual where 1 = :B1 and 2 > :B1' into v_cnt using 1; dbms_output.put_line(v_cnt); end;
However, the following will succeed because the SQL code is in fact an anonymous block:
begin execute immediate 'declare v_cnt number; begin select count(*) into v_cnt from dual where 1 = :B1 and 2 > :B1; dbms_output.put_line(v_cnt); end;' using 1; end;
Pretty cool stuff.
-
Hi guys,.
When a SQL using bind variables histograms afftect the excution plan how?
For example
There is a table 'TEST' a column a number, varchar2 (100) b, c. tank (100).
100000 rows in this table and the 90000 column rows a value is 1, the other value is 2-10 by 100rows.
Now this column a histogram and a btree index only has on a;
Here is sample code
number of a_v var;
exec: a_v: = 10;
Select * from test where a =: a_v.
The plan of the excution is full table scan.
If I don't use of variable binding. It will scan the index.
I remember that a document mentioned that "do not use histograms using bind variables.
But why?
I disabled same bind variable peeking?
Thank you guys. Looking forward to your response.Longfei Wei says:
Thanks Centinul this article is useful for me, but it is not explained why histograms do not work well with bind variables.Thanks again.
Longfei,
Jonathan Lewis article is very good - another look at this article. Histograms peuvent work with bind variable, but the end result is usually not the desired result. Bind variables are used to reduce the number of different execution plans. The histograms are used to find what is supposed to be the best execution plan for the predicates provided and in the case of the bind variables, those are peeked from the bind variable values. Thus, if you have a histogram on a column and for hard analysis of a SQL statement and the most common value in this column is presented in the binding variable - this execution plan is considered by the optimizer to be the 'best' execution plan for the bind variable values provided. Suppose now that instead the less popular value in the column is specified - the optimizer peut produce a very different for the same SQL statement execution plan, which is optimized for the less popular value (this can be a scan of the index systematic range, rather than a full table scan). Now suppose the execution plan may not change when change of variable values bind - if you have a single popular value and many unpopular values, if the analysis lasts is performed with the popular single value, you might find that all subsequent runs of this SQL statement to perform full table scans, even if only a few rows in the table are selected.
Here's a quick test on the Oracle 11.2.0.2 database to demonstrate:
CREATE TABLE T1 ( C1 NUMBER, C2 NUMBER, C3 VARCHAR2(300)); INSERT INTO T1 SELECT * FROM (SELECT ROWNUM C1, DECODE(MOD(ROWNUM,100),99,99,1) C2, RPAD('A',300,'A') C3 FROM DUAL CONNECT BY LEVEL <= 1000000) ORDER BY C2; CREATE INDEX IND_T1_C2 ON T1(C2); EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>USER,TABNAME=>'T1',CASCADE=>TRUE,METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE 254')
The foregoing has created a table with 1 000 000 lines where 99% of the lines have a value of 1 in C2 and 1% have a value of 99, and lines are inserted with a perfect setting in cluster factor because of the ORDER BY clause. A histogram has been created on the indexed column.
Let's try a test, we'll search a unpopular value 2 for the connection variable:
VARIABLE N1 NUMBER EXEC :N1:=2 SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1; no rows selected SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST')); SQL_ID c7su63uw7nch6, child number 0 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1 Plan hash value: 236868917 ------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | ------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 0 |00:00:00.01 | 3 | 1 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 5957 | 0 |00:00:00.01 | 3 | 1 | |* 2 | INDEX RANGE SCAN | IND_T1_C2 | 1 | 5957 | 0 |00:00:00.01 | 3 | 1 | ------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("C2"=:N1)
Thus, there is no selected row, the optimizer predicts that 5 957 lines would be returned and a path to the index has been selected. Path of this index would also be appropriate for the value of the bind variable 1? We will continue the trial, this time by choosing the 99 for the binding variable value:
EXEC :N1:=99 SET TIMING ON SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1; ... 10000 rows selected. Elapsed: 00:00:05.35 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST')); SQL_ID c7su63uw7nch6, child number 0 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1 Plan hash value: 236868917 --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 10000 |00:00:00.02 | 1783 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 5957 | 10000 |00:00:00.02 | 1783 | |* 2 | INDEX RANGE SCAN | IND_T1_C2 | 1 | 5957 | 10000 |00:00:00.01 | 690 | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("C2"=:N1)
Once more, the optimizer predicts 5 957 lines could be found even if 10,000 rows have been retrieved. Note also that the number of children is always 0. We will continue the trial, this time with the bind variable value of 1:
EXEC :N1:=1 SET AUTOTRACE TRACEONLY STATISTICS SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1; 990000 rows selected. Elapsed: 00:00:18.78 Statistics --------------------------------------------------- 1 recursive calls 1 db block gets 108571 consistent gets 0 physical reads 96 redo size 21958348 bytes sent via SQL*Net to client 726508 bytes received via SQL*Net from client 66001 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 990000 rows processed SET AUTOTRACE OFF
Because I used AUTOTRACE to prevent 990 000 lines scrolling on the screen, I have to specify the SQL_ID and CHILD_NUMBER to retrieve the execution plan:
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('c7su63uw7nch6',0,'ALLSTATS LAST')); SQL_ID c7su63uw7nch6, child number 0 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1 Plan hash value: 236868917 --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 10000 |00:00:00.02 | 1783 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 5957 | 10000 |00:00:00.02 | 1783 | |* 2 | INDEX RANGE SCAN | IND_T1_C2 | 1 | 5957 | 10000 |00:00:00.01 | 690 | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("C2"=:N1)
Who can be the execution plan that was used because it shows that 10,000 rows have been retrieved. We will try again, this time with CHILD_NUMBER 1:
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('c7su63uw7nch6',1,'ALLSTATS LAST')); SQL_ID c7su63uw7nch6, child number 1 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1 Plan hash value: 3617692013 ------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 990K|00:00:00.83 | 108K| |* 1 | TABLE ACCESS FULL| T1 | 1 | 988K| 990K|00:00:00.83 | 108K| ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("C2"=:N1)
The foregoing shows the actual plan that has been used. Sharing the adjustment slider (first available with Oracle Database 11.1) is reached and forced to re-evaluate the execution plan to avoid a very slow recovery through the index - which won't happen before 11.1 database Oracle.
Just to illustrate:
ALTER SESSION SET OPTIMIZER_FEATURES_ENABLE='10.2.0.4'; VARIABLE N1 NUMBER EXEC :N1:=2 SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1; no rows selected Elapsed: 00:00:00.00 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST')); SQL_ID c7su63uw7nch6, child number 2 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1 Plan hash value: 236868917 --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 0 |00:00:00.01 | 3 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 5957 | 0 |00:00:00.01 | 3 | |* 2 | INDEX RANGE SCAN | IND_T1_C2 | 1 | 5957 | 0 |00:00:00.01 | 3 | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("C2"=:N1)
Note in the above that the CHILD_NUMBER is now 2.
Continues:
EXEC :N1:=99 SET TIMING ON SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1; 10000 rows selected. Elapsed: 00:00:05.31 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST')); SQL_ID c7su63uw7nch6, child number 2 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1 Plan hash value: 236868917 --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 10000 |00:00:00.02 | 1783 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 5957 | 10000 |00:00:00.02 | 1783 | |* 2 | INDEX RANGE SCAN | IND_T1_C2 | 1 | 5957 | 10000 |00:00:00.01 | 690 | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("C2"=:N1)
The CHILD_NUMBER is always 2.
Continues:
EXEC :N1:=1 SET AUTOTRACE TRACEONLY STATISTICS SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1; 990000 rows selected. Elapsed: 00:00:16.91 Statistics --------------------------------------------------- 0 recursive calls 0 db block gets 175927 consistent gets 0 physical reads 0 redo size 21958348 bytes sent via SQL*Net to client 726508 bytes received via SQL*Net from client 66001 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 990000 rows processed SET AUTOTRACE OFF SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('c7su63uw7nch6',2,'ALLSTATS LAST')); SQL_ID c7su63uw7nch6, child number 2 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */ C1, C2 FROM T1 WHERE C2 = :N1 Plan hash value: 236868917 --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 990K|00:00:01.63 | 175K| | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 5957 | 990K|00:00:01.63 | 175K| |* 2 | INDEX RANGE SCAN | IND_T1_C2 | 1 | 5957 | 990K|00:00:00.68 | 67932 | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("C2"=:N1)
The foregoing is the execution plan for CHILD_NUMBER 2 - notice that this time he reports 990 000 recovered lines, it's the execution that was used - adaptive cursor sharing plan do not have take effect and force the re-evaluation of the implementation plan - implementation plan has NOT been changed for a full table scan. That's the risk you take if you allow histograms on columns that have an uneven distribution of values and bind variables are used in the WHERE clause that refers to the column.
Charles Hooper
Co-author of "Expert Oracle practices: Oracle Database Administration of the Oak Table.
http://hoopercharles.WordPress.com/
IT Manager/Oracle DBA
K & M-making Machine, Inc. -
Estimate of poor cardinality using Bind Variables
Hi I'm using the 11.2.0.4.0 Oracle version. I have a query that is underway for the plan of the poor execution by the estimate of poor cardinality for two tables (I've extracted and published this part only) as I mentioned below, the individual conditions for which the estimate goes bad and moving entire query execution path.
These are for two tables and currently we use BIND variable for them in our code, and I notice, its best estimate gives with literals. I need to know how to handle this scenario that I need this query to execute for all types of volumes. Is there something I can do without changing the code, as it works well for most of the execution? In the current scenario of the main query that uses those below tables providing a plan (index + nested loop) that works very well for small volume, but running for 10 hr + for large volume as ideally its going to the same regime.
And Yes, most time that this request will be hit for small volume, but killing some appearance of large volume presents the performance of the queries.
Here are the values of the variable binding.B1 VARIABLE VARCHAR2 (32);
B2 VARIABLE VARCHAR2 (32);
B3 VARIABLE NUMBER;
B4 VARIABLE VARCHAR2 (32);
B7 VARIABLE VARCHAR2 (32);
B5 VARIABLE NUMBER;
B6 VARIABLE NUMBER;EXEC: B1: = 'NONE ';
EXEC: B2: = NULL;
EXEC: B3: = 0;
EXEC: B4: = NULL;
EXEC: B7: = NULL;
EXEC: B5: = 0;
EXEC: B6: = 0;---- For TABLE1------- -- Published Actual VS Etimated cardinality -- With bind values select * from TABLE1 SF WHERE ( (SF.C1_IDCODE = :B4) OR (NVL (:B4, 'NONE') = 'NONE')) AND ( (SF.C2_ID = :B3) OR (NVL (:B3, 0) = 0)); Plan hash value: 2590266031 ----------------------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem | ----------------------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 28835 |00:00:00.08 | 2748 | 46 | | | | |* 1 | TABLE ACCESS STORAGE FULL| TABLE1 | 1 | 11 | 28835 |00:00:00.08 | 2748 | 46 | 1025K| 1025K| | ----------------------------------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - storage((("SF"."C1_IDCODE"=:B4 OR NVL(:B4,'NONE')='NONE') AND ("SF"."C2_ID"=:B3 OR NVL(:B3,0)=0))) filter((("SF"."C1_IDCODE"=:B4 OR NVL(:B4,'NONE')='NONE') AND ("SF"."C2_ID"=:B3 OR NVL(:B3,0)=0))) -- With literals select * from TABLE1 SF WHERE ( (SF.C1_IDCODE = null) OR (NVL (null, 'NONE') = 'NONE')) AND ( (SF.C2_ID = 0) OR (NVL (0, 0) = 0)); Plan hash value: 2590266031 -------------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | -------------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 28835 |00:00:00.03 | 2748 | | | | | 1 | TABLE ACCESS STORAGE FULL| TABLE1 | 1 | 28835 | 28835 |00:00:00.03 | 2748 | 1025K| 1025K| | -------------------------------------------------------------------------------------------------------------------------------------- --------For TABLE2 ----------------------- -- Published Autotrace plan, as it was taking long time for completion, and actual cardinality is 45M, but its estimating 49 With bind value--- --withbind value select * from TABLE2 MTF WHERE ( (MTF.C6_CODE = TRIM (:B2)) OR (NVL (:B2, 'NONE') = 'NONE')) AND ( (MTF.C3_CODE = :B1) OR (NVL (:B1, 'NONE') = 'NONE')) AND ( (MTF.C4_CODE = :B7) OR (:B7 IS NULL)) AND ( (MTF.C5_AMT <= :B6) OR (NVL (:B6, 0) = 0)) AND ( (MTF.C5_AMT >= :B5) OR (NVL (:B5, 0) = 0)); Execution Plan ---------------------------------------------------------- Plan hash value: 1536592532 ----------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ----------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 49 | 10437 | 358K (1)| 01:11:43 | | | | 1 | PARTITION RANGE ALL | | 49 | 10437 | 358K (1)| 01:11:43 | 1 | 2 | |* 2 | TABLE ACCESS STORAGE FULL| TABLE2 | 49 | 10437 | 358K (1)| 01:11:43 | 1 | 2 | ----------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - storage(("MTF"."C4_CODE"=:B7 OR :B7 IS NULL) AND ("MTF"."C3_CODE"=:B1 OR NVL(:B1,'NONE')='NONE') AND ("MTF"."C5_AMT"<=TO_NUMBER(:B6) OR NVL(:B6,0)=0) AND ("MTF"."C5_AMT">=TO_NUMBER(:B5) OR NVL(:B5,0)=0) AND ("MTF"."C6_CODE"=TRIM(:B2) OR NVL(:B2,'NONE')='NONE')) filter(("MTF"."C4_CODE"=:B7 OR :B7 IS NULL) AND ("MTF"."C3_CODE"=:B1 OR NVL(:B1,'NONE')='NONE') AND ("MTF"."C5_AMT"<=TO_NUMBER(:B6) OR NVL(:B6,0)=0) AND ("MTF"."C5_AMT">=TO_NUMBER(:B5) OR NVL(:B5,0)=0) AND ("MTF"."C6_CODE"=TRIM(:B2) OR NVL(:B2,'NONE')='NONE')) -- with literal select * from TABLE2 MTF WHERE ( (MTF.C6_CODE = TRIM (null)) OR (NVL (null, 'NONE') = 'NONE')) AND ( (MTF.C3_CODE = 'NONE') OR (NVL ('NONE', 'NONE') = 'NONE')) AND ( (MTF.C4_CODE = null) OR (null IS NULL)) AND ( (MTF.C5_AMT <= 0) OR (NVL (0, 0) = 0)) AND ( (MTF.C5_AMT >= 0) OR (NVL (0, 0) = 0)); Execution Plan ---------------------------------------------------------- Plan hash value: 1536592532 ----------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ----------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 45M| 9151M| 358K (1)| 01:11:41 | | | | 1 | PARTITION RANGE ALL | | 45M| 9151M| 358K (1)| 01:11:41 | 1 | 2 | | 2 | TABLE ACCESS STORAGE FULL| TABLE2 | 45M| 9151M| 358K (1)| 01:11:41 | 1 | 2 | ----------------------------------------------------------------------------------------------------------- select column_name,num_nulls,num_distinct,density from dba_tab_col_statistics where table_name='TABLE2' and column_name in ('C3_CODE','C4_CODE','C5_AMT','C6_CODE'); C3_CODE 0 65 0.0153846153846154 C4_CODE 0 2 0.5 C5_AMT 0 21544 4.64166357222429E-5 C6_CODE 1889955 71 0.0140845070422535
933257 wrote:
((SF. C1_IDCODE =: B4) OR (NVL (: B4, 'NONE') = 'NONE'))
In fact for literals, I did not find any section of the predicate after running the sql code with activation "set autotrace traceonly explain."
The main problem is with another large query whose cardinality is underestimated due to the presence of these table (table1, table2) with the above mentioned clause, and the query is for the analysis of index + nested with values of Bind loops and take 10 hr +, whereas with literals, its completion in ~ 8minutes with FTS + Hash Join.
Your real problem is that you try to have just a single SQL query handle all POSSIBLE thanks to the use of embedded FILTERS ' either / or ' filters in the WHERE clause. You want only a select this OPTION to run whatever filters have been selected at run time by the user or the application using it. And it would never work. You really need to SELECT different queries for different combinations of filter conditions.
Why? Think for a minute. How Oracle works internally? A SQL SELECT query gets analyzed and an execution plan is produced which is stored in the library cache and gets REUSED on all subsequent executions of this query - except in certain cases where there may exist several plans run through several cursors of the child. So with only SELECT a query you only AN execution plan in the library cache, to be used by all THE executions of this query, regardless of the value of your run-time binding variables.
Lets put another way - each library cache execution plan is associated with a SQL statement. If you want a DIFFERENT execution plan then you need run a DIFFERENT SQL statement. That's how you get a different execution plan - by running a different SQL statement. Running the SAME SQL query generally you will get the SAME execution plan every time.
In addition, because of the "either / or" filters that you use you will end up generally with a full Table Scan on each of the referenced tables. Why? Given that the optimizer must produce an implementation plan that manages all possible contingencies for all values of possible bind variables in the SELECT. If the optimizer should choose to use any index based on one of these "either / or" filters then it would only help performance when real value was provided, but it would be really bad if a NULL value was supplied. If the optimizer ends up ignoring the index because they are not always optimal for all possible input values and instead chose a plan that is "good enough" for all input values possible. That means that it will use a scanning Table full.
I hope you can see that it is precisely what is happening for you with your query. You select this OPTION to manage the different combinations of filter, which leads to the execution plan only one, which leads to scans full Table on the referenced tables in these ' either / or ' filters.
The solution? Build queries SELECT DIFFERENT when input values are NULL. How you do that? Read this article to ask Tom that tells you:
http://www.Oracle.com/technetwork/issue-archive/2009/09-Jul/o49asktom-090487.html
To sum up - when you have real value for a bind variable 'bind_var1' add the following filter to your CHOICE:
AND column_name1 =: bind_var1
When the binding variable is NULL, add the filter according to your CHOICE:
AND (1 = 1 OR: bind_var1 IS NULL)
Now, you'll have 2 queries SELECT must be performed, which have exactly the same number of variables in the same order bind, which is important. When you then run one of these variations, Oracle can analyze and optimize each one SEPARATELY, with a single execution by the SELECT query plan.
When you provide a real value, the filter is a normal 'column = value' that the optimizer can use all indexes on this column, because NULL values are not referenced.
When there is no real value, the optimizer will analyze the '1 = 1 GOLD' and realize that "1 = 1" is set to TRUE and GOLD, it is quite TRUE regardless because the binding variable is null or not. This means that the optimizer will actually REMOVE this filter, because it filters nothing because it is always TRUE. You will end up with an operating plan based on the other filters in the query, which is what you want because you have no filter on this column.
What is it - producing distinct SELECT queries to determine if you have a real value to filter or not you end up with DIFFERENT execution plans for each of them, and each of them is OPTIMAL for this particular set of filters. Now you get good performance for each variation of the performance of the SELECTION, rather than sometimes good and sometimes very bad when using SELECT only one. It is impossible to try to get multiple shots of execution 'optimal' out of a SELECT query. That's why you get mediocre performance under different bound the values of the variables.
John Brady
-
Estimates of cardinality for index range scan with bind variables
Oracle 11.2.0.4
I am struggling to explain that the cardinality estimates for a scan of the index systematic range when using the bind variable.
Consider the following query:
SELECT /*+ INDEX(t1) */ * FROM t1 WHERE source_id <= ?;
Cardinalities for the INDEX RANGE SCAN and ACCESS of the TABLE are the same for different literal predicates, for example, source_id < = 5:
------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 50 | 350 | 12 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 50 | 350 | 12 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IX1 | 50 | | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("SOURCE_ID"<=5)
If a variable binding is used instead of a literal, the overall selectivity is 5%. However, why the optimizer based on CSSTidy gives a cardinality estimated 11 for the scan of the index systematic range? As with the predicates literal, surely the cardinalities of the index range scan and access table should be the same?
------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 50 | 350 | 5 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 50 | 350 | 5 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IX1 | 11 | | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("SOURCE_ID"<=TO_NUMBER(:A))
Unit test code:
CREATE TABLE t1 ( id NUMBER , source_id NUMBER ); CREATE INDEX ix1 ON t1 (source_id); INSERT INTO t1 SELECT level , ora_hash(level,99)+1 FROM dual CONNECT BY level <= 1000; exec DBMS_STATS.GATHER_TABLE_STATS(user,'T1') EXPLAIN PLAN FOR SELECT /*+ INDEX(t1) */ * FROM t1 WHERE source_id <= 5; SELECT * FROM TABLE(dbms_xplan.display); EXPLAIN PLAN FOR SELECT /*+ INDEX(t1) */ * FROM t1 WHERE source_id <= :a; SELECT * FROM TABLE(dbms_xplan.display);
There are various places where the optimizer uses an assumption, and lie unpeekable (and of Villa "unknowable value") introduced guess.
For unpeekable binds the conjecture for column<= {unknown}="" is="" 5%="" for="" table="" access="" (hence="" 50="" rows="" out="" of="" 1,000),="" but="" it's="" 0.009="" for="" index_column="">=><= {unknown},="" which="" means="" i="" was="" expecting="" to="" see="" 9="" as="" the="" row="" estimate="" on="" the="" index="" range="">=>
I just ran some quick tests, and EXPLAIN the PLAN seems to just use 0.011 selectivity in this case (in different versions of Oracle) although if we do the bind variable unpeekable at run time (and sample dynamic block etc.) optimization for execution is 0.009%.
Concerning
Jonathan Lewis
Update: and this is a very old reference to the 0.009 (and 0.0045 for ' between the ' when it is applied to a clue: cost based Oracle - access Chapter 4 single B-tree )
-
Bind Variables on the view objects child definition
JDeveloper 12 c
I have an interesting question. I have a view (AisWebModulePrivsVO) object that uses a bindvariable hardcoded in the view object.
SELECT * FROM SYS. DBA_ROLE_PRIVS where DEALER =: bvUserName
If I put this in the request module I can programmatically set the variable binding (view object contains the getter/setter for the binding variable).
AisWebModulePrivsVOImpl voTest = am.getAisWebModulePrivsVI ();
voTest.setbvUserName ("ARAWLS");
voTest.executeQuery ();
System.out.println ("test reports:" + voTest.getRowCount ());
and get the correct number of records based on return on the user and database roles. If it works.
What does NOT work, it is when this display object is a recording of 'the child' to another display object (as specified by a link between the two and by setting the object from a point of view as one child of the other in the module of the application).
AppModule looks like this:
CgRefCodesVO
AisWebModulePrivsVO
In this case, I have a view called cgRefCodeVO parent object. There is a link between this and the AisWebModulePrivsVO. The relationship works.
AISMenuAppModuleImpl m = ADFUtils.getApplicationModuleForDataControl (appMod) (AISMenuAppModuleImpl);
CgRefCodesVOImpl cgRefVO = am.getCgRefCodes1 ();
AisWebModulePrivsVOImpl modsVO = am.getAisWebModulePrivs1 ();
modsVO.setbvDBUserName ("ARAWLS"); This doesn't seem to work here...
cgRefVO.executeQuery ();
All lines rs = cgRefVO.getRowSet ();
RS. Reset();
While (rs.hasNext ()) {}
CgRefCodesVORowImpl CgRefRow = rs.next ((CgRefCodesVORowImpl));
System.out.println ("RvLowValue:" + CgRefRow.getAttribute ("RvLowValue"));
RowIterator aisModulesRowIter = CgRefRow.getAisWebModulePrivs ();
System.out.println ("number of children:" + aisModulesRowIter.getRowCount ());
}
The code compiles and runs. She translates: "County of the child: 0" for each row returned by the
I also tried:
VM VariableValueManager = modsVO.ensureVariableManager ();
vm.setVariableValue ("bvDBUserName", "ARAWLS");
And:
modsVO.setNamedWhereClauseParam ("bvDBUserName", "ARAWLS");
and (of ( )
@Override
protected void executeQueryForCollection (Object, object, Object [] object2, int i) {}
I coded everything hard to see if it would work.
setNamedWhereClauseParam ("bvDBUserName", "ARAWLS");
super.executeQueryForCollection (object, object2, i);
}
and from there, I changed around the order to execute the objects in view.
How can I set the variable binding in the object view child?
Thank you
Stuart
It is an interesting example how ADF works up to a certain point... then you need to start to make cuts to modify its behavior as you wish.
I decided that it was just easier to delete 'the child' parent (in the app module) and create a view of criteria on this subject for what would basically query the records to get the same results, like a child.
Perhaps not as elegant, but so much easier.
Thanks for your help.
Stuart
-
Passing literal as a bind variable in Jena
Hi all
We are able to use bind variable with the id RDFVID. However, if we want to check for a literal using the jena/joseki adapter we are not able to perform the same operation. In our case the literal is of type string.
We use:
* WLS 12.1.0.3.
* Adapter Jena 2.11.1.
* Joseki 3.4.4.
* ARQ 2.9.2.
We try to run the following query on the stop of joseki.
PREFIX foaf: http://xmlns.com/FOAF/0.1/ >
PREFIX vcard: http://www.w3.org/2001/vCard-RDF/3.0# >
PREFIX xsd: http://www.w3.org/2001/XMLSchema# >
PREFIX oext: < http://Oracle.com/Semtech/Jena-adaptor/ext/function# >
PREFIX ORACLE_SEM_FS_NS: http://Oracle.com/Semtech#no_fall_back, ALLOW_DUP = T, s2s >
PREFIX ORACLE_SEM_HT_NS: http://Oracle.com/Semtech#monitor >
PREFIX ORACLE_SEM_UEAP_NS: http://oracle.com/semtech#f$ RDFVID % 20 (ORACLE_ORARDF_RES2VID(?)) >
PREFIX ORACLE_SEM_UEPJ_NS: http://Oracle.com/Semtech#f $RDFVID >
PREFIX ORACLE_SEM_UEBV_NS: http://Oracle.com/Semtech# 'Lee' >
SELECT? f
WHERE
{graph? g {? vcard:N p? vn.}}
? VN vcard:Family? f.
? FOAF:title p 'Sen'.}
}
The result set is empty. Replace the line 'ORACLE_SEM_UEBV_NS PREFIX: <http://oracle.com/semtech# "Lee"> "by any Variant is to be given an error or the empty set. (Some variants (& quot;)) Lee & quot; Lee, "Lee" & #39; Lee & #39; )
When we use the generated SQL code of jena/joseki, we are able to get the right result if we execute the query even in SQLDeveloper. To use the variable binding is "Lee" (the binding variable is the price included). This will give you a correct result in withdrawal.
Kind regards
Max
Hi Max,.
In the area of the UEBV, you must put "Lee" encoded in URL string
Please, try the following and see if it helps.
% 22Lee % 22
Thank you
Zhe Wu
-
Convert SQL to take advantage of the Bind Variables
Hi all
Is it possible to convert the SQL below so I can enjoy variable Bind? It's just my personal way of followed by the name of the script that I use on a daily basis... the file is passed to a point that its about 2K lines long, and whenever I run this specific file to get a script name, it creates a new SQL in the database pool shared... I tried to change this option to use bind variables , but it doesn't seem to work properly and I wanted what suggestion of the community...
ACCEPT script_name_like prompt 'ENTER SCRIPT NAME OR HIT ENTER TO GET ALL SCRIPT NAME OR PUT PART OF THE SCRIPT NAME : ' WITH help_script AS ( SELECT 'top_seg_tab_obj_ash' AS Script_Name, 'top segment by tot wait time' AS Description, '# of mins to go back' AS INPUT FROM dual UNION ALL SELECT 'v$_tab' AS Script_Name, 'shows list v$ views' AS Description, 'view name like' AS INPUT FROM dual UNION ALL SELECT 'dba_tab' AS Script_Name, 'shows list dba views' AS Description, 'view name like' AS INPUT FROM dual UNION ALL SELECT 'nls_params' AS Script_Name, 'shows list of current NLS setting for DB/INST/SESS' AS Description, 'no Input Needed' AS INPUT ) SELECT upper(script_name) AS "MY SCRIPT NAME", upper(description) AS description, upper(INPUT) AS INPUT FROM help_script WHERE script_name LIKE nvl('%&script_name_like%', script_name) ;
Hello
user13454469 wrote:
Hi all
Is it possible to convert the SQL below so I can enjoy variable Bind? It's just my personal way of followed by the name of the script that I use on a daily basis... the file is passed to a point that its about 2K lines long, and whenever I run this specific file to get a script name, it creates a new SQL in the database pool shared... I tried to change this option to use bind variables , but it doesn't seem to work properly and I wanted what suggestion of the community...
- ACCEPT script_name_like invites ' ENTER NAME or HIT ENTER to GET ALL THE SCRIPT NAME or PART OF THE SCRIPT the SCRIPT NAME: '
- WITH help_script AS
- (SELECT "top_seg_tab_obj_ash" AS Script_Name,
- "upper segment by tot queue time" AS Description,.
- "# of minutes to go back" AS INPUT
- OF the double
- UNION ALL SELECT ' v$ _tab "AS Script_Name,.
- "Show list views$ v ' AS Description,.
- 'show the name as' AS ENTRY
- OF the double
- UNION ALL SELECT 'dba_tab' AS Script_Name,
- "Show list views dba" AS Description,.
- 'show the name as' AS ENTRY
- OF the double
- UNION ALL SELECT 'nls_params' AS Script_Name,
- 'displays the list of current NLS parameter for DB/INST/SESS' AS Description,.
- ("No input is necessary" IN ENTRY)
- SELECT upper (script_name) AS "MY SCRIPT NAME",
- Upper (Description) as a description,
- Upper (Input) AS INPUT
- OF help_script
- WHERE script_name AS nvl (script_name ' % & script_name_like %',);)
The WHERE clause (last line) of is the only place where you are using the proxy & script_name_like? If so:
-ACCEPT command is exactly the same as before
ACCEPT script_name_like invites ' ENTER NAME or HIT ENTER to GET ALL THE SCRIPT NAME or PART OF THE SCRIPT the SCRIPT NAME: '
VARIABLE script_name_like_b VARCHAR2 (30)
EXEC: script_name_like_b: = '% & script_name_like;
WITH the help _script AS
...
WHERE script_name AS NVL (: script_name_like_b, script_name);
-
When I go from ODP.NET to the ODP.NET managed some of my questions begins to throw errors missing bind variable.
I reproduced with a simple example that uses a variable called liaison: unitName
It's the example SQL:
SELECT
: unitName
Of
DOUBLE
Now, if I add a comment at the beginning of the SQL like this:
-Text with: unitName
SELECT
: unitName
Of
DOUBLE
It works, but if I have a variable binding in a comment that is located on a number of the 'same' line, I get ORA-01006:
This causes the error:
-First line comment
-Text with: unitName
SELECT
: unitName
Of
DOUBLE
Kind regards
-Tommy
I was able to reproduce this problem. I filed Bug 19433348 on your behalf.
The circumstances in which the bug occurs are fairly easy to get around.
(1) remove the colon in the second commented line.
(2) add a space between the '\n' and ' - '.
If you are one of those things, you won't encounter the bug behavior.
-
on the ora-01006: there is no bind variable
Hi all of you, I have this dynamic sql code:
DECLARE
CLOB v_query;
number of CPT;
Start
v_query: ='
SELECT
County (TBA. ANT_ID)
Of
...
WHERE TBA. ANT_FUT_ID = TFT. FUT_ID
AND TBA. ANT_KATEGORIE_CODE_ID = TAKCL. ANT_KATEGORIE_CODE_ID (+)
AND TBA. ANT_KFZ_REIHEN_ID = TKR. KFZ_REIHEN_ID (+)
AND TBA. ANT_ID = F1. ANT_ANT_ID (+)
AND TBA. ANT_ID = F2. ANT_ANT_ID (+)
AND TBA. ANT_ID = F3. ANT_ANT_ID (+)
AND TBA. ANT_ID = ERS.ers_bdk (+)
AND TBA. ANT_ID = F1_2.ANT_ANT_ID (+)
AND TBA. ANT_ID = F2_3.ANT_ANT_ID (+)
AND TBA. ANT_ID = UPM. MFU_ANT_ID (+)
AND UPM. MFU_NIETGEOMETRIE_ID = NG. NG_ID (+)
AND UPM. MFU_MATRIZEN_BEICHNUNG_ID = MZB. MZB_ID (+)
--------------------
-Suchkriterien: -.
--------------------
-Creator
AND DECODE (ERS.ers_id, NULL, '%', ERS.ers_name) AS DECODE (": 1", "%", "') |" ' || :1 ||''''|| DECODE('':1'',''%'',''')
-Fahrzeug
AND DECODE (TKR.NAME, NULL, '%', TKR.NAME) AS DECODE (": 2", "%", "') |" ' || :2 ||''''|| DECODE('':2'',''%'',''')
-BDK
AND DECODE (fuege_db.bdk_nummer (TBA. ANT_ID, "."), NULL, "PERCENT",
fuege_db.bdk_nummer (TBA. ANT_ID, ".") ) LIKE '%'. :3||'' %''
-Technology
AND TBA. ANT_FUT_ID AS DECODE (": 4%","","') |" ' || :4 ||''''|| DECODE('':4'',''%'',''')
-Art
AND ((TBA. ANT_WFP_ID is null and 1 = DECODE('':5'',NULL,1,1,1)) ou (TBA.)) ANT_WFP_ID is not null and 2 = DECODE (": 5 cm, 2,2,2)))
-ADV
AND TBA. ANT_VTA = decode (cm: 6 cm, 1.1, TBA.) ANT_VTA) ';
run immediately v_query
in USING cpt
"Dominik Hussmann."
"AU736_Q7_SUV,"
'' ,
"WPS Stahl."
'',
'0' ;
end;
In execution, I have this error: ora-01006: bind variable does not exist, after analysis, I found that the problem is with the settings: 5 and: 6, I do not understand that they have the same syntax
as variables bind 1,2,3 and 4.
Than you for any suggestion.
I hope that you realize that there are 13 variable bind in your sql, not 6?
Variables are related by mail. You cannot use the same variable to link twice, they will be 2 separate bind variable.
For example, you use: 1 three times, so you must provide three arguments, in this case, three times the same value.
-
Hi all
I have a variable refcursor, to which I will assign running queries.
All are defined (union) queries, with 5 or 6 selects the union, each select returns the same variable where clause. Value of the variable will be known at run time.
For example: (just an example)
{code}
Start
v_sql: = ' select col1, col2
of the Department
where dept_no =: 1
Union
Select col1, col2
of eur_dept
where dept_no =: 1
Union
Select col1, col2
of us_dept
where dept_no =: 1 ';
Open the v_ref_cur for v_sql using 20, 20, 20;
-rest of the logic
------------
-----------------
end;
{code}
Question is how to avoid the bind variable value repeat (in the open statement). Is there a way I can mention value 20 only once when the cursor is opened.
Thank you!
DS says:
Question is how to avoid the bind variable value repeat (in the open statement). Is there a way I can mention value 20 only once when the cursor is opened.
Yes - can be done using a dynamic anonymous block to create the refcursor (containing the SQL text), as oppose to the creation of the refcursor directly from the SQL text.
Not an approach I consider myself - unless there is absolutely no better way to address this particular issue.
SQL > var refcursor c.
SQL >
SQL > declare
News 2 sys_refcursor;
3. start
4 immediate execution
5 ' declare
6 varchar2 (4000) var1: =: 1; -/ / simple definition var - used several times
7. start
open 8: news for
9 select * from emp where mgr = var1
10 the union all the
11. Select * from emp where empno = var1;
12 end; »
13 using 7698-past the variable once
14 in the news; -getting refcursor as answer
15
16: c: = cur;
end 17;
18.
PL/SQL procedure successfully completed.
SQL >
SQL > print c
EMPNO, ENAME, JOB HIREDATE DEPTNO COMM SAL MGR
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 1981/02/20 00:00:00 1600 300 30
7521 WARD SALESMAN 7698 1981/02/22 00:00:00 1250 500 30
7654 MARTIN SALESMAN 7698 1981/09/28 00:00:00 1250 1400 30
7844 TURNER SALESMAN 7698 1981-09-08 00:00:00 1500 0 30
7900 JAMES CLERK 7698 1981/12/03 00:00:00 950 30
7698 BLAKE MANAGER 7839 1981/05/01 00:00:00 2850 30
6 selected lines.
SQL >
-
Hello
If I run this query from my sql * more customer, what is the difference between substitution and the bind variable then?
Select * from emp where empno = & x;
Select * from emp where empno =: x;
In both cases, my request that will be sent to the server for execution will be completed (with no reserved space).
The only difference I can think is that we cannot use bind variable instead of table_names & the names of column, but we can use substitution variables. As shown below
Select * from: var where empno =:-this will not work when they are under values dynamically
Select * from & var where empno = & y - it works.
So what else is the difference between substitution and the bind variable then?
Thank you
When you use a variable substitiution in sqlplus or any other client that supports, the client interprets the value of the variable and puts it into the sql statement. So, if you have:
Select * from emp where emp_id = & n
The customer gets the value you supply and replaces the variable substitution with the value you provide, thus, if you enter 10 the query that the sql engine sees is actually:
Select * from emp where emp_id = 10
This is why you must put quotes around a variable substitution when using it as a string in a projection or a predicate. In other words, if you want to query by last_name with a substitution variable, you would do something like:
Select * from emp where last_name = '& ln '.
When you use a link as variable:
Select * from emp where emp_id =: n
the client passes the sql statement, exactly as you wrote it and at the same time he says also, moreover, the value of: n is 10. If you then change the value of: n 20 the customer always going the same exact sql statement, but this time, says the value of: n is 20.
As others have pointed out, with a substitution variable each sql statement with a new value for the variable is a brand new, never seen before trial and must be hard to be analyzed by the SQL engine. Whenever you use a new value of a variable to bind the SQL remains the same, so the SQL engine can avoid the hard analysis (expensive).
John
-
See criteria and bind variables
Greetings experts,
I use JDev, version: 11.1.2.3.0
Recently, I came across this situation. I created a variable binding (in VO), which is used inside a criterion for the VO even. This criterion to display is called within a method that is declared within a class of java of implementation of AppModule (which is exposed on the Client Instance), and through a managed bean I supply the parameter required to initialize the variable binding (and then get the results). This works fine, and the page that uses the domain controller for this appmodule runs without error.
The point is that I have the same VO, used inside an another appModule (and another page uses, it's DC). I need to use this variable binding in this case, but if I click edit on this VO second, inside the second presentation of appModule interface, I can see that the criteria for the view, is in the "Available" tab, but in the section 'Setting bind' it shows the binding variable said first.
I am as a matter of fact, receiving and error on this second page if I do some operations, saying this:
Caused by: java.sql.SQLException: try to set a parameter name that does not intervene in the SQL: partyNum
at oracle.jdbc.driver.OraclePreparedStatement.setNullAtName(OraclePreparedStatement.java:5384)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setNullAtName(OraclePreparedStatementWrapper.java:1451)
at oracle.jbo.server.OracleSQLBuilderImpl.bindParamValue(OracleSQLBuilderImpl.java:4695)
at oracle.jbo.server.BaseSQLBuilderImpl.bindParametersForStmt(BaseSQLBuilderImpl.java:3673)
at oracle.jbo.server.ViewObjectImpl.bindParametersForCollection(ViewObjectImpl.java:21459)
at oracle.jbo.server.QueryCollection.buildResultSet(QueryCollection.java:1197)
SQL error in the preparation of the statement. Instruction: SELECT PartiesContracts.CONTRACT_IDCONTRACT, PartiesContracts.PARTY_TYPE, PartiesContracts.PARTY_NUM, PartiesContracts.ROLE PARTIES_CONTRACTS PartiesContracts WHERE PartiesContracts.CONTRACT_IDCONTRACT =: Bind_Idcontract
(The binding variable is called, partyNum)
My question is, can I do to avoid using this variable to link on the second page of appModule only? It seems to be called always regardless the fact if I call the appropriate support bean method that triggers the initialization process.
Thank you for your time.
Have you defined the binding variable 'partyNum' as requires it? In this case, you need to specify every time. You can set the variable as not mandatory and it might work.
The solution would be to set another VO with the same base, without the "partyNum" bind variable and VC and use in the other AM.
Timo
-
How to pass a list as a bind variable in SQL Developer?
How can I pass a list as a bind variable in SQL Developer?
The following query in SQL Developer so work I put ": prmRegionID = 2.
SELECT COUNTRY_ID,
COUNTRY_NAME
OF HUMAN RESOURCES. COUNTRY
WHERE IN REGION_ID (: prmRegionID);
The problem is that I can't find how to set ": prmRegionID = 2, 3.
I know that I can replace ": prmRegionID" by a proxy '& prmRegionID '. The above query will work well with"& prmRegionID = 2" and with "& prmRegionID = 2, 3". "
But with this solution, I lost all the benefit of the use of bound variables (analysis hard against soft parse, possibility of SQL injection, etc.).
I'm learning how to do this in SQL, as well as the use of UDT in this thread: How to move a list as a bind variable?
But with this solution, I've lost nice SQL Developer user interface. In SQL developer, it is easy to test a query using the standard binding variable. When we start the application, a pop up asking for a value of the variable binding.
With the UDT, the interface request always variable binding standard. You have an idea on how I can get a variable string binding (such as 1, 2, 10) in a set of NUMBER or VARCHAR2? This way I would be able to launch a standard query in SQL Developer to test my application.
Can someone tell me what is the best approach to this?
Thank you in advance,
MBHi Blais,
Thank you for trying the SQL and PL/SQL instance before coming here - it was definitely the right approach, and you've got some very good suggestions there. Your needs for a invite only bind to the value in the clause list, I think I have a possible solution. I'll introduce you to a list of characters, so you'll have to tweak it for other types of data. First, add the following to your schema:
create or replace TYPE bind_tab_typ AS TABLE OF VARCHAR2(4000); create or replace FUNCTION comma_to_table(iv_raw IN VARCHAR2) RETURN bind_tab_typ PIPELINED IS ltab_lname dbms_utility.lname_array; ln_len BINARY_INTEGER; BEGIN dbms_utility.comma_to_table(list => iv_raw ,tablen => ln_len ,tab => ltab_lname); FOR i IN 1 .. ln_len LOOP PIPE ROW (ltab_lname(i)); END LOOP; END;
Now you can write a query, say for scott.dept, as follows, and have executed statement ask the value list in the clause as a single binding variable:
select * from dept where dname in ( select * from table( comma_to_table( :BNDS )) );
When you are prompted, provide the list of values separated by a single comma without any extra spaces.
I don't know if the Varchar2 (4000) really needs to be which is great. I use it because that's what dbms_utility.lname_array uses.
Kind regards
Gary
SQL development team -
Performance tests: bind variables
When you write a SQL for the application, I want to do some performance testing of SQL before providing to JAVA developers. I understand that I need to test using bind variables, can someone guide me how do? What are the best tools out there to achieve? Please provide some guidance. Thank you!Rinne says:
I read more about bind variable and I can test the use of bind variables. I understand that testing SQL using bind variables is a closer representation of the real world. Even when queries have large tables, the performance would be similar if I run the query using literals twice (to avoid hard analysis) compared to tests with bind variables? I am trying to understand more thoroughly the need for tests with bind variables. Why we take more time than the other? Thank you!The main thing is that the opimizer will / can do if bind variables different optimization techniques are used or not.
There are two contradictory effects its regarding the binding settings.Effect 1: Reuse of cursor
If the same is done again and again and again. Maybe different sessions. Then using binding settings is essential. Why? Because the same cursor can be reused, which saves a lot of time for analysis. This occurs mainly in OLTP systems. The idea behind this is that to do the same action, just for a different ID (ID in order for example) will result in an identical implementation plan.The result: Faster analysis time and less consumption of memory, because the same cursor can be resused between different sessions.
Effect 2: Correct assumptions
According to a filter expression, some using the value of the OBC will make an assumption based on statistical data the number of rows is returned because of this expression and the value.
Speculation between a literal value and a bound value may be different. In many cases exist technical opimization (bind peeking etc.) to the same literal conjecture binded proposal.But there are exceptions, for example a condition such as the following will result in different estimates
column between 10 and 20
column between :P1 and :P2
There are as well other effects.
Result: The CBO can make assumptions better if literals. But most of the cases the proposal is identical.
Conclusion: Literal values are useful if you do large queries where the output size depends strongly on the parameters provided, and where you run that very few of these (OLAP) queries.
Binding settings are usfull when the same execution (OLTP) need a grand plan number of queries.
Maybe you are looking for
-
How to install Firefox on Opensuse 11.4 29
I intend to install Firefox on Opensuse 11.4 29 29 Firefox as last selenium (used for the automation of GUI) supports up to 29 OpenSUSE 11.4 due to my project requirements. After you have installed Opensuse 114, I knew this version of firefox by defa
-
I forgot my security questions I forgot my security questions and it keeps asking me every time that I want to buy the app... It is ok with my iPhone but for mac, it asks me to answer due to the purchase of first time on Mac... and can even change to
-
I can't update my iPad to ios9 because the error message says that my update cannot be verified because I am not connected to the Internet, but I am logged in?
-
Battery handling with the HP HDX16t Premium Series notebook PC
Hi guys, I was just wondering how this PC manages the charging of the battery. As in, it completely cut off the power supply to the battery when it is fully charged, as if the battery was not yet in the laptop or would he keep it loads whenever he g
-
program guard fence family tree Maker, why?
Whenever I started with Family tree maker, it closes & I get a message from microsoft that a program unknown if he stops & they will check a solution, but I never get an answer.