Home » SQL & PL/SQL » SQL & PL/SQL » Use ANSI standard JOIN syntax
Use ANSI standard JOIN syntax [message #598030] Wed, 09 October 2013 18:10 Go to next message
nataliafoster26
Messages: 64
Registered: October 2013
Member
does anyone know what this mean? Use ANSI standard JOIN syntax
for example i have this code.
 SELECT resv_num, unit_date
      FROM p_resv_unit ru, p_pm_unit_night pun
     WHERE pun.property_id = in_property_id
       AND pun.pm_unit_num = cvUnitNum
       AND pun.unit_date BETWEEN start_date AND end_date
       AND pun.resv_unit_id = ru.resv_unit_id;
 nResvNum         p_resv_unit.resv_num%TYPE;
 dUnitDate        p_pm_unit_night.unit_date%TYPE;
   tabUnitNum   Util_Pkg.var_arr;
   nUnitCnt     NUMBER := 1;
   bResFound BOOLEAN; 
BEGIN


and is it a good idea to change it, because both ways it works?

[Updated on: Wed, 09 October 2013 18:10]

Report message to a moderator

Re: Use ANSI standard JOIN syntax [message #598032 is a reply to message #598030] Wed, 09 October 2013 20:00 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
>and is it a good idea to change it,
It?
Good? Compared to what?
it? To what do you refer?

>because both ways it works?
it?
Both ways?

Can you be any more obtuse & unclear?
Re: Use ANSI standard JOIN syntax [message #598035 is a reply to message #598030] Thu, 10 October 2013 00:04 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
nataliafoster26 wrote on Thu, 10 October 2013 04:40
does anyone know what this mean? Use ANSI standard JOIN syntax


Oracle has introduced ANSI-compliant joins into its SQL implementation in 9i.

Few good links -
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:6585774577187 - T.Kyte's reply to old vs new syntax
http://www.orafaq.com/node/2618 - John Watson's blog
http://www.oracle-base.com/articles/9i/ansi-iso-sql-support.php - by Tim Hall

Regards,
Lalit
Re: Use ANSI standard JOIN syntax [message #598036 is a reply to message #598030] Thu, 10 October 2013 00:26 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Just replace "," between "p_resv_unit ru" and "p_pm_unit_night pun" by "JOIN" and "WHERE" by "ON".

Re: Use ANSI standard JOIN syntax [message #598038 is a reply to message #598030] Thu, 10 October 2013 01:37 Go to previous messageGo to next message
pablolee
Messages: 2882
Registered: May 2007
Location: Scotland
Senior Member
Hi Natalia. Yes, you are right, both ways work. They're the same from a performance perspective too. Your post is a little hard to understand, but it looks to me that you are asking whether it is necessary/better practice to use the ANSI syntax over the older, Oracle syntax.
Personally, I much prefer the ANSI syntax, primarily because
It is so much easier to read.
It keeps all your joins separate from all your predicates.
It prevents silly mistakes like accidentally leaving out a single (+) on a set of join predicates in the where clause, thereby negating your outer join.
It is ridiculously easy to switch between inner, left, right, and full joins.
I'm also fairly certain that the Oracle syntax has one or two restrictions that the ANSI syntax does not (but for the life of me I can't remember them right now - maybe they'll be in one of the links that Lalit posted)
Re: Use ANSI standard JOIN syntax [message #598042 is a reply to message #598038] Thu, 10 October 2013 02:06 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
With regard to restrictions on the use of ANSI syntax, I don't remember any published list. The only issue I can recall with 11.2.x was with fast refresh of materialized views. I don't have the example to hand, but I think fast refresh of a join view failed when using ANSI.
Overall, as I have said many times, I think ANSI syntax is astronomically superior: far easier to maintain, far less prone to error.
Re: Use ANSI standard JOIN syntax [message #598043 is a reply to message #598038] Thu, 10 October 2013 02:10 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Quote:
I'm also fairly certain that the Oracle syntax has one or two restrictions that the ANSI syntax does not


The first example is FULL OUTER JOIN which does not exist in Oracle syntax.

Re: Use ANSI standard JOIN syntax [message #598044 is a reply to message #598043] Thu, 10 October 2013 02:21 Go to previous messageGo to next message
pablolee
Messages: 2882
Registered: May 2007
Location: Scotland
Senior Member
Michel Cadot wrote on Thu, 10 October 2013 08:10

Quote:
I'm also fairly certain that the Oracle syntax has one or two restrictions that the ANSI syntax does not


The first example is FULL OUTER JOIN which does not exist in Oracle syntax.


Hmm, but that can, of course, be achieved by unioning a left and a right join (which does exactly the same amount of work (but with MUCH more code) so I'm not sure that I'd agree that that is a restriction as such.

I would point out, that I could very well be 'mis-remembering' (I'm getting on a bit you know Wink )
Re: Use ANSI standard JOIN syntax [message #598045 is a reply to message #598042] Thu, 10 October 2013 02:23 Go to previous messageGo to next message
pablolee
Messages: 2882
Registered: May 2007
Location: Scotland
Senior Member
John Watson wrote on Thu, 10 October 2013 08:06
With regard to restrictions on the use of ANSI syntax, I don't remember any published list.
Ok, but I was talking about restrictions on the Oracle syntax Smile.
Quote:
The only issue I can recall with 11.2.x was with fast refresh of materialized views. I don't have the example to hand, but I think fast refresh of a join view failed when using ANSI.
I did not know that, thanks, I'll maybe have a trawl to see if i can find a discussion on it.
Quote:
Overall, as I have said many times, I think ANSI syntax is astronomically superior: far easier to maintain, far less prone to error.
Preaching to the converted here John. Agree 100%, I was hoping that my post made that clear, maybe not.
Re: Use ANSI standard JOIN syntax [message #598047 is a reply to message #598038] Thu, 10 October 2013 02:30 Go to previous messageGo to next message
Roachcoach
Messages: 1576
Registered: May 2010
Location: UK
Senior Member
pablolee wrote on Thu, 10 October 2013 07:37
Hi Natalia. Yes, you are right, both ways work. They're the same from a performance perspective too.


I don't have a citation handy so you'll have to take my word for it but certain (older) versions, the optimizer was better with the Oracle syntax. I believe certain operations have slid the other way in more recent (11+) versions.

As I say I cant remember exactly what and what versions but whilst generally true, it's not always.

Of course, the chances of that being your biggest problem when it comes to tuning...well...that'd be a nice problem to have Wink
Re: Use ANSI standard JOIN syntax [message #598048 is a reply to message #598047] Thu, 10 October 2013 02:39 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
I'm getting different performance characteristics (12.1.0.1), which I wasn't expecting:
orclz>
orclz> set autot trace exp
orclz> select ename,dname from emp,dept where emp.deptno(+)=dept.deptno
  2  union
  3  select ename,dname from emp,dept where emp.deptno=dept.deptno(+);

Execution Plan
----------------------------------------------------------
Plan hash value: 2227970010

-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |    29 |  1218 |    12  (50)| 00:00:01 |
|   1 |  SORT UNIQUE         |      |    29 |  1218 |    12  (50)| 00:00:01 |
|   2 |   UNION-ALL          |      |       |       |            |          |
|*  3 |    HASH JOIN OUTER   |      |    15 |   630 |     6   (0)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| DEPT |     4 |    88 |     3   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL| EMP  |    14 |   280 |     3   (0)| 00:00:01 |
|*  6 |    HASH JOIN OUTER   |      |    14 |   588 |     6   (0)| 00:00:01 |
|   7 |     TABLE ACCESS FULL| EMP  |    14 |   280 |     3   (0)| 00:00:01 |
|   8 |     TABLE ACCESS FULL| DEPT |     4 |    88 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("EMP"."DEPTNO"(+)="DEPT"."DEPTNO")
   6 - access("EMP"."DEPTNO"="DEPT"."DEPTNO"(+))

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - this is an adaptive plan

orclz> select ename,dname from emp full outer join dept using(deptno);

Execution Plan
----------------------------------------------------------
Plan hash value: 51889263

-------------------------------------------------------------------------------
| Id  | Operation             | Name     | Rows  | Bytes | Cost (%CPU)| Time
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |          |    15 |   240 |     6   (0)| 00:00:0
|   1 |  VIEW                 | VW_FOJ_0 |    15 |   240 |     6   (0)| 00:00:0
|*  2 |   HASH JOIN FULL OUTER|          |    15 |   630 |     6   (0)| 00:00:0
|   3 |    TABLE ACCESS FULL  | DEPT     |     4 |    88 |     3   (0)| 00:00:0
|   4 |    TABLE ACCESS FULL  | EMP      |    14 |   280 |     3   (0)| 00:00:0
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

orclz>
interesting that the cardinality estimates are off with the native syntax. I'm not going to investigate this further now (time to start chargeable work) .
Re: Use ANSI standard JOIN syntax [message #598050 is a reply to message #598044] Thu, 10 October 2013 02:43 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator
pablolee wrote on Thu, 10 October 2013 09:21
Michel Cadot wrote on Thu, 10 October 2013 08:10

Quote:
I'm also fairly certain that the Oracle syntax has one or two restrictions that the ANSI syntax does not


The first example is FULL OUTER JOIN which does not exist in Oracle syntax.


Hmm, but that can, of course, be achieved by unioning a left and a right join (which does exactly the same amount of work (but with MUCH more code) so I'm not sure that I'd agree that that is a restriction as such.

I would point out, that I could very well be 'mis-remembering' (I'm getting on a bit you know Wink )


Yes, hopefully you can always have another SQL syntax otherwise Oracle would not be complete regarding SQL standard.

Another example is when you have an OR in the outer condition:
drop table t1;
drop table t2;
create table t1 (col1a int, col1b int, col1c int);
create table t2 (col2a int, col2b int);
insert into t1 values (1, 2, 3);
insert into t1 values (1, 2, 4);
insert into t1 values (2, 3, 4);
insert into t1 values (3, 3, 4);
insert into t1 values (3, 3, 5);
insert into t1 values (2, 4, 5);
insert into t2 values (1, 2);
insert into t2 values (3, 5);
commit;

SQL> select * 
  2  from t1 left outer join t2
  3       on t1.col1a = t2.col2a or t1.col1b = t2.col2b
  4  /
     COL1A      COL1B      COL1C      COL2A      COL2B
---------- ---------- ---------- ---------- ----------
         1          2          3          1          2
         1          2          4          1          2
         2          3          4
         3          3          4          3          5
         3          3          5          3          5
         2          4          5

6 rows selected.

SQL> select *
  2  from t1, T2
  3  where t1.col1a = t2.col2a (+)
  4     or t1.col1b = t2.col2b (+)
  5  /
   or t1.col1b = t2.col2b (+)
               *
ERROR at line 4:
ORA-01719: outer join operator (+) not allowed in operand of OR or IN

Re: Use ANSI standard JOIN syntax [message #598051 is a reply to message #598050] Thu, 10 October 2013 02:45 Go to previous messageGo to next message
pablolee
Messages: 2882
Registered: May 2007
Location: Scotland
Senior Member
Quote:
Another example is when you have an OR in the outer condition:

I think that's the one I was thinking of (IIRC I saw it posted on OTN - not even that long ago!). Cheers Michel
icon3.gif  Re: Use ANSI standard JOIN syntax [message #598052 is a reply to message #598050] Thu, 10 October 2013 02:46 Go to previous messageGo to next message
Michel Cadot
Messages: 68645
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

And another one is when you have at the same time an outer and and inner condition against a constant (with the same tables and data):
SQL> select *
  2  from t1 left outer join t2 
  3       on t2.col2a = t1.col1a and t1.col1b = 3
  4  where t1.col1c = 4
  5  /
     COL1A      COL1B      COL1C      COL2A      COL2B
---------- ---------- ---------- ---------- ----------
         3          3          4          3          5
         1          2          4
         2          3          4

3 rows selected.

The equivalent in Oracle syntax would be:
SQL> select * 
  2  from t1, t2
  3  where t2.col2a (+) = t1.col1a 
  4    and t1.col1b (+) = 3
  5    and t1.col1c = 4
  6  /
     COL1A      COL1B      COL1C      COL2A      COL2B
---------- ---------- ---------- ---------- ----------
         3          3          4          3          5
         2          3          4

2 rows selected.

But in this case Oracle replaces the outer condition in the constant to an inner one:
SQL> set autotrace traceonly explain
SQL> select * 
  2  from t1, t2
  3  where t2.col2a (+) = t1.col1a 
  4    and t1.col1b (+) = 3
  5    and t1.col1c = 4
  6  /

Execution Plan
----------------------------------------------------------
Plan hash value: 1823443478

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     2 |   130 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN OUTER   |      |     2 |   130 |     7  (15)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| T1   |     2 |    78 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   |     2 |    52 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("T2"."COL2A"(+)="T1"."COL1A")
   2 - filter("T1"."COL1B"=3 AND "T1"."COL1C"=4)

Re: Use ANSI standard JOIN syntax [message #598053 is a reply to message #598048] Thu, 10 October 2013 02:55 Go to previous messageGo to next message
pablolee
Messages: 2882
Registered: May 2007
Location: Scotland
Senior Member
John, very interesting. I was always under the impression that oracle did the same amount of work either way (more weight to the ANSI argument - if it was ever needed). Thanks for this.
Re: Use ANSI standard JOIN syntax [message #598059 is a reply to message #598048] Thu, 10 October 2013 03:42 Go to previous message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
John Watson wrote on Thu, 10 October 2013 13:09
I'm getting different performance characteristics (12.1.0.1), which I wasn't expecting


John,

As pablolee said, even I always thought that it takes the same amount of work in either of the syntax. However, quite surprisingly it is not.

I don't have version 12 at my work right now, but I could test it in version 11, and I have seen this first time -

SQL> SELECT * FROM v$version
  2  /
 
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE	11.2.0.2.0	Production
TNS for IBM/AIX RISC System/6000: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production

SQL> EXPLAIN PLAN FOR SELECT ENAME, DNAME FROM EMP FULL OUTER JOIN DEPT USING (DEPTNO)
  2  /
 
Explained

SQL> SELECT * FROM table(dbms_xplan.display)
  2  /
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2779170970
--------------------------------------------------------------------------------
| Id  | Operation             | Name     | Rows  | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |          |     4 |    56 |    31   (4)| 00:00:01
|   1 |  VIEW                 | VW_FOJ_0 |     4 |    56 |    31   (4)| 00:00:01
|*  2 |   HASH JOIN FULL OUTER|          |     4 |   160 |    31   (4)| 00:00:01
|   3 |    TABLE ACCESS FULL  | DEPT     |     3 |    60 |    15   (0)| 00:00:01
|   4 |    TABLE ACCESS FULL  | EMP      |     4 |    80 |    15   (0)| 00:00:01
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")
Note
-----
   - dynamic sampling used for this statement (level=2)
 
20 rows selected

SQL> EXPLAIN PLAN FOR SELECT ENAME, DNAME
  2    FROM EMP, DEPT
  3   WHERE EMP.DEPTNO(+) = DEPT.DEPTNO
  4  UNION
  5  SELECT ENAME, DNAME
  6    FROM EMP, DEPT
  7   WHERE EMP.DEPTNO = DEPT.DEPTNO(+)
  8  /
 
Explained

SQL>  SELECT * FROM table(dbms_xplan.display)
  2  /
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1800384560
-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |     8 |   320 |    63  (53)| 00:00:01 |
|   1 |  SORT UNIQUE         |      |     8 |   320 |    63  (53)| 00:00:01 |
|   2 |   UNION-ALL          |      |       |       |            |          |
|*  3 |    HASH JOIN OUTER   |      |     4 |   160 |    31   (4)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| DEPT |     3 |    60 |    15   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL| EMP  |     4 |    80 |    15   (0)| 00:00:01 |
|*  6 |    HASH JOIN OUTER   |      |     4 |   160 |    31   (4)| 00:00:01 |
|   7 |     TABLE ACCESS FULL| EMP  |     4 |    80 |    15   (0)| 00:00:01 |
|   8 |     TABLE ACCESS FULL| DEPT |     3 |    60 |    15   (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("EMP"."DEPTNO"(+)="DEPT"."DEPTNO")
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
   6 - access("EMP"."DEPTNO"="DEPT"."DEPTNO"(+))
Note
-----
   - dynamic sampling used for this statement (level=2)
 
25 rows selected


I make a small change in the query, and -
SQL> EXPLAIN PLAN FOR SELECT ENAME, DNAME
  2    FROM EMP, DEPT
  3   WHERE EMP.DEPTNO(+) = DEPT.DEPTNO
  4  UNION ALL
  5  SELECT ENAME, DNAME
  6    FROM EMP, DEPT
  7   WHERE EMP.DEPTNO = DEPT.DEPTNO(+)
  8     AND EMP.DEPTNO IS NULL
  9  /
 
Explained

SQL>  SELECT * FROM table(dbms_xplan.display)
  2  /
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 912395105
----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |     5 |   200 |    61  (51)| 00:00:01 |
|   1 |  UNION-ALL          |      |       |       |            |          |
|*  2 |   HASH JOIN OUTER   |      |     4 |   160 |    31   (4)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| DEPT |     3 |    60 |    15   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| EMP  |     4 |    80 |    15   (0)| 00:00:01 |
|*  5 |   HASH JOIN OUTER   |      |     1 |    40 |    31   (4)| 00:00:01 |
|*  6 |    TABLE ACCESS FULL| EMP  |     1 |    20 |    15   (0)| 00:00:01 |
|   7 |    TABLE ACCESS FULL| DEPT |     3 |    60 |    15   (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("EMP"."DEPTNO"(+)="DEPT"."DEPTNO")
   5 - access("EMP"."DEPTNO"="DEPT"."DEPTNO"(+))
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
   6 - filter("EMP"."DEPTNO" IS NULL)
Note
-----
   - dynamic sampling used for this statement (level=2)
 
25 rows selected

Regards,
Lalit
Previous Topic: PL/SQL Block Structure
Next Topic: Dynamic Table Partitioning
Goto Forum:
  


Current Time: Fri Apr 26 05:16:48 CDT 2024