Re: How to pass bind variable value into a view

From: Charles Hooper <hooperc2000_at_yahoo.com>
Date: Fri, 9 Oct 2009 08:13:51 -0700 (PDT)
Message-ID: <561aabaa-70e3-4e43-8d46-9a13e2a5692d_at_r36g2000vbn.googlegroups.com>



On Oct 8, 2:54 pm, UXDBA <unixdb..._at_googlemail.com> wrote:
> All,
>
> RDBMS :  9.2.0.8
> (snip)
> question:
>
> a) Is there any way we can pass bind variable to the inner query with
> using view v1 ( i know BIND
> var cannot be passed to DDL)but any other way you would suggest to
> achieve the same result.
>
> Regards

I think that we need a full test case to verify what you are seeing. I had to change the table names slightly due to existing objects with those names:
CREATE TABLE TT1 AS
SELECT
  ROWNUM COL1,
  CEIL(ROWNUM/2000) COL2,
  LPAD('A',200,'A') COL3
FROM
  DUAL
CONNECT BY
  LEVEL<=10000000;

CREATE TABLE TT2 AS
SELECT
  ROWNUM COL1,
  CEIL(ROWNUM/2000) COL2,
  LPAD('A',200,'A') COL3
FROM
  DUAL
CONNECT BY
  LEVEL<=10000000;

CREATE UNIQUE INDEX IND_TT1 ON TT1(COL1); CREATE INDEX IND_TT2 ON TT2(COL2); EXEC DBMS_STATS.GATHER_TABLE_STATS
(OWNNAME=>USER,TABNAME=>'TT1',CASCADE=>TRUE) EXEC DBMS_STATS.GATHER_TABLE_STATS
(OWNNAME=>USER,TABNAME=>'TT2',CASCADE=>TRUE) CREATE OR REPLACE VIEW VV1 (
  VV1_COL1,
  VV1_COL2)
AS
SELECT
  TT1.COL1,
  TT2.COL2
FROM
  TT1,
  TT2
WHERE
  TT1.COL1=TT2.COL2; VARIABLE N1 NUMBER EXEC :N1:=1000 SELECT
  *
FROM
  VV1
WHERE
  VV1.COL1=:N1; ERROR at line 6:
ORA-00904: "VV1"."COL1": invalid identifier

Notice that Oracle returned an error as the columns have been aliased by the view.

SELECT
  *
FROM
  VV1
WHERE
  VV1.VV1_COL1=:N1;   VV1_COL1 VV1_COL2
---------- ----------

      1000       1000
      1000       1000
      1000       1000

...

2000 rows selected.

SET LINESIZE 120
SET PAGESIZE 2000 SPOOL C:\VV1_PLAN1024.TXT SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,NULL)); SPOOL OFF Plan hash value: 2691474176


| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)|
Time     |

------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 8 (100)| | | 1 | NESTED LOOPS | | 1986 | 19860 | 8 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN| IND_TT1 | 1 | 6 | 2 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | IND_TT2 | 1986 | 7944 | 6 (0)|
00:00:01 |

Predicate Information (identified by operation id):


   2 - access("TT1"."COL1"=:N1)
   3 - access("TT2"."COL2"=:N1)

The Predicate Information shows that Oracle did push in the value of the N1 bind variable into the view.

SHOW PARAMETER OPTIMIZER

NAME                                 TYPE        VALUE
------------------------------------ ----------- --------
optimizer_dynamic_sampling           integer     2
optimizer_features_enable            string      10.2.0.4
optimizer_index_caching              integer     0
optimizer_index_cost_adj             integer     100
optimizer_mode                       string      ALL_ROWS
optimizer_secure_view_merging        boolean     TRUE


ALTER SESSION SET OPTIMIZER_FEATURES_ENABLE='9.2.0'; SELECT
  *
FROM
  VV1
WHERE
  VV1.VV1_COL1=:N1;   VV1_COL1 VV1_COL2
---------- ----------

      1000       1000
      1000       1000
      1000       1000

...

2000 rows selected.

SPOOL C:\VV1_PLAN920.TXT SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,NULL)); SPOOL OFF Plan hash value: 2691474176


| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)|
Time     |

------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 9 (100)| | | 1 | NESTED LOOPS | | 1986 | 19860 | 9 (12)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN| IND_TT1 | 1 | 6 | 3 (34)| 00:00:01 | |* 3 | INDEX RANGE SCAN | IND_TT2 | 1986 | 7944 | 7 (15)|
00:00:01 |

Predicate Information (identified by operation id):


   2 - access("TT1"."COL1"=:N1)
   3 - access("TT2"."COL2"=:N1)

Notice that the plan is identical when the optimizer is pretending to be compatible with Oracle 9.2.0.x.

SHOW PARAMETER OPTIMIZER

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------
optimizer_dynamic_sampling           integer     1
optimizer_features_enable            string      9.2.0
optimizer_index_caching              integer     0
optimizer_index_cost_adj             integer     100
optimizer_mode                       string      CHOOSE
optimizer_secure_view_merging        boolean     TRUE


Now for the other version of the query:
SELECT
  *
FROM
  (SELECT
    TT1.COL1,
    TT2.COL2
  FROM
    TT1,
    TT2
  WHERE
    TT1.COL1=TT2.COL2
    AND TT1.COL1=:N1);       COL1 COL2
---------- ----------

      1000       1000
      1000       1000
      1000       1000

...

2000 rows selected.

SPOOL C:\VV1_PLAN920-2.TXT SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,NULL)); SPOOL OFF Plan hash value: 2691474176


| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)|
Time     |

------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 9 (100)| | | 1 | NESTED LOOPS | | 1986 | 19860 | 9 (12)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN| IND_TT1 | 1 | 6 | 3 (34)| 00:00:01 | |* 3 | INDEX RANGE SCAN | IND_TT2 | 1986 | 7944 | 7 (15)|
00:00:01 |

Predicate Information (identified by operation id):


   2 - access("TT1"."COL1"=:N1)
   3 - access("TT2"."COL2"=:N1)

Same plan as was seen for the other SQL statement. Let's check the optimizer at release 10.2.0.4:
ALTER SESSION SET OPTIMIZER_FEATURES_ENABLE='10.2.0.4'; SELECT
  *
FROM
  (SELECT
    TT1.COL1,
    TT2.COL2
  FROM
    TT1,
    TT2
  WHERE
    TT1.COL1=TT2.COL2
    AND TT1.COL1=:N1);       COL1 COL2
---------- ----------

      1000       1000
      1000       1000
      1000       1000

...

2000 rows selected.

SPOOL C:\VV1_PLAN1024-2.TXT SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,NULL)); SPOOL OFF Plan hash value: 2691474176


| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)|
Time     |

------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 8 (100)| | | 1 | NESTED LOOPS | | 1986 | 19860 | 8 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN| IND_TT1 | 1 | 6 | 2 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | IND_TT2 | 1986 | 7944 | 6 (0)|
00:00:01 |

Predicate Information (identified by operation id):


   2 - access("TT1"."COL1"=:N1)
   3 - access("TT2"."COL2"=:N1)

Same plan again. The above DBMS_XPLAN.DISPLAY_CURSOR function requires a minimum of Oracle 10.1. For 9.2.0.x you should be able to used the following method:
EXPLAIN PLAN FOR
SELECT
  *
FROM
  (SELECT
    TT1.COL1,
    TT2.COL2
  FROM
    TT1,
    TT2
  WHERE
    TT1.COL1=TT2.COL2
    AND TT1.COL1=:N1); SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); Plan hash value: 2691474176


| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)|
Time     |

------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1986 | 19860 | 8 (0)| 00:00:01 | | 1 | NESTED LOOPS | | 1986 | 19860 | 8 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN| IND_TT1 | 1 | 6 | 2 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | IND_TT2 | 1986 | 7944 | 6 (0)|
00:00:01 |

Predicate Information (identified by operation id):


   2 - access("TT1"."COL1"=TO_NUMBER(:N1))    3 - access("TT2"."COL2"=TO_NUMBER(:N1))

Notice the problem in the Predicate Information above with explain plan when numeric bind variables are used, which may lead to inaccurate execution plans. The DBMS_XPLAN.DISPLAY_CURSOR function pulls the actual execution plan from the library cache.

EXPLAIN PLAN FOR
SELECT
  *
FROM
  VV1
WHERE
  VV1.VV1_COL1=:N1; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); Plan hash value: 2691474176


| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)|
Time     |

------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1986 | 19860 | 8 (0)| 00:00:01 | | 1 | NESTED LOOPS | | 1986 | 19860 | 8 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN| IND_TT1 | 1 | 6 | 2 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | IND_TT2 | 1986 | 7944 | 6 (0)|
00:00:01 |

Predicate Information (identified by operation id):


   2 - access("TT1"."COL1"=TO_NUMBER(:N1))    3 - access("TT2"."COL2"=TO_NUMBER(:N1))

Same plan again, even when testing with
OPTIMIZER_FEATURES_ENABLE='9.2.0'. It might be helpful to verify that you have not made an error in the analysis due to table and column names. Try the above test case to see if the same plan in received in all cases.

Charles Hooper
IT Manager/Oracle DBA
K&M Machine-Fabricating, Inc. Received on Fri Oct 09 2009 - 10:13:51 CDT

Original text of this message