tags:

views:

526

answers:

10

Hello, I develop against Oracle databases. When I need to manually write (not use an ORM like hibernate), I put join statements in the where clause sections.

for example (this is simplistic just to illustrate the style):

Select *
from customers c, invoices i, shipment_info si
where c.customer_id = i.customer_id
    and i.amount > 999.99 
    and i.invoice_id = si.invoice_id(+)  -- added to show how outer joins can be supported in this style
order by i.amount, c.name

I learned this style from an OLD oracle DBA. I have since learned that this is not standard SQL syntax. Other than being non-standard and much less database portable, are there any other repercussions to using this format?

Thanks, Jay

+4  A: 

Some people will say that this style is less readable, but that's a matter of habit. From a performance point of view, it doesn't matter, since the query optimizer takes care of that.

ammoQ
Except that for certian outer join queries the older syntax cab easily give incorrect results, and therefore should be avoided.
Charles Bretana
Charles: Agreed, outer joins using the (+) syntax are a PITA. Hard to comprehend, error-prone...
ammoQ
On the other hand the ANSI syntax has been more buggy and also has given incorrect results. I don't recall a situation where the oracle join synatx did so though ... do you have an example?
David Aldridge
I find it to be the exact opposite. It is more readable having the query split into columns, tables, joins and other limiting factors. I find the (+) syntax to be much easier to work with than the ANSI. Personal preference I guess.
Dougman
The (+) syntax is used by companies other than Oracle?
R. Bemrose
A: 

Actually, this syntax is more portable than a JOIN, because it will work with pretty much any database, whereas not everybody supports the JOIN syntax (Oracle Lite doesn't, for example [unless this has changed recently]).

MusiGenesis
The older join syntax is wrong in numerous cases where *outer* join logic is required.
Charles Bretana
A: 

This is Transact SQL syntax, and I'm not quite sure how "unportable" it is - it is the main syntax used in Sybase, for example (Sybase supports ANSI syntax as well) as well as many other databases (if not all).

The main benefits to ANSI syntax is that it allows you to write some fairly tricky chained joins that T-SQL prohibits

DVK
+5  A: 

The biggest issue that I have run into with this format is the tendency to forget some join's WHERE clause, thereby resulting in a cartesian product. This is particularly common (for me, at least) when adding a new table to the query. For example, suppose an ADDRESSES table is thrown into the mix and your mind is a bit forgetful:

SELECT *
  FROM customers c, invoices i, addresses a
 WHERE c.customer_id = i.customer_id
   AND i.amount > 999.99
 ORDER BY i.amount, c.name

Boom! Cartesian product! :)

Adam Paynter
This is true, but like all (err most) syntax errors, won't you see the problem when you try to run, and then fix it? That has been my experience in this matter.
Jay
@Jay: True enough. I still find it annoying when you get a big, runaway query started on low-resource Oracle servers. :)
Adam Paynter
Jay, sadly no most people won't see the problem, they just add a distinct and go on their merry way.
HLGEM
Cartesian products are also allowed using the JOIN syntax by leaving out the JOIN condition. This is a bit more obvious in the JOIN syntax but still quite possible. And, @HLGEM, adding DISTINCT to the SELECT will not address the issue of a Cartesian production especially in the common case where a primary key is returned from each participating table.
Larry Lustig
@Larry: Interesting, I didn't even know that you could leave out the join condition!
Adam Paynter
@Adam I *think* the standard behavior when a `JOIN` condition is omitted is a natural join where it does an implicit `=` for each pair of columns with matching names, but it probably varies between RDBMS.
Hank Gay
If you specify the join type, i.e. `INNER JOIN`, most DBMSes force you to include an ON or USING statement.
R. Bemrose
+5  A: 

I don't like the style because it makes it harder to determine which WHERE clauses are for simulating JOINs and which ones are for actual filters, and I don't like code that makes it unnecessarily difficult to determine the original intent of the programmer.

Hank Gay
+1 for "I don't like code that makes it unnecessarily difficult to determine the original intent of the programmer"
Adam Paynter
+1  A: 

This is a standard SQL syntax, just an older standard than JOIN. There's a reason that the syntax has evolved and you should use the newer JOIN syntax because:

  1. It's more expressive, clearly indicating which tables are JOINed, the JOIN order, which conditions apply to which JOIN, and separating out the filtering WHERE conditions from the JOIN conditions.

  2. It supports LEFT, RIGHT, and FULL OUTER JOINs, which the WHERE syntax does not.

I don't think you'll find the WHERE-type JOIN substantially less portable than the JOIN syntax.

Larry Lustig
+3  A: 

As long as you don't use the ANSI natural join feature I'm OK with it.

I found this quote by – ScottCher, I totally agree:

I find the WHERE syntax easier to read than INNER JOIN - I guess its like Vegemite. Most people in the world probably find it disgusting but kids brought up eating it love it.

Robert Merkwürdigeliebe
+1 on the vegemite comment :-) Although I don't agree with your technical point: what's your problem with natural joins?
Arthur Reutenauer
You should be specific about the columns you join. Natural joins are error prone.For example (from ask tom site)Consider a model like this:create table emp ( empno, deptno, ename );create table dept ( deptno, dname, empno /* person responsible for this dept */ );now, generate a list of enames and the dname they work in using a natural join.
Robert Merkwürdigeliebe
OK, my bad. I naively imagined that natural joins were based on foreign keys, and just added those joins, not all the ones you could guess by column names. The behaviour you describe is indeed bad.
Arthur Reutenauer
Even if it uses FK's it does not know which to choose. I have a fk from emp.deptno to dept.deptno and one from dept.empno to emp.empno.Think about what happens when you add or rename columns. Yuck
Robert Merkwürdigeliebe
Right. That sucks.
Arthur Reutenauer
+2  A: 

The old style join is flat out wrong in some cases (outer joins are the culprit). Although they are more or less equivilent when using inner joins, they can generate incorrect results with outer joins, especially if columns on the outer side can be null. This is because when using the older syntax the join conditions are not logically evaluated until the entire result set has been constructed, it is simply not possible to express a condition on a column from outer side of a join that will filter records when the column can be null because there is no matching record.

As an example:

Select all Customers, and the sum of the sales of Widgets on all their Invoices in the month Of August, where the Invoice has been processed (Invoice.ProcessDate is Not Null)

using new ANSI-92 Join syntax

 Select c.name, Sum(d.Amount)
 From customer c
    Left Join Invoice I 
        On i.custId = c.custId
            And i.SalesDate Between '8/1/2009' 
                      and '8/31/2009 23:59:59'
            And i.ProcessDate Is Not Null
    Left Join InvoiceDetails d 
        On d.InvoiceId = i.InvoiceId
            And d.Product = 'widget'
 Group By c.Name

Try doing this with old syntax... Because when using the old style syntax, all the conditions in the where clause are evaluated/applied BEFORE the 'outer' rows are added back in, All the UnProcessed Invoice rows will get added back into the final result set... So this is not possible with old syntax - anything that attempts to filter out the invoices with null Processed Dates will eliminate customers... the only alternative is to use a correllated subquery.

Charles Bretana
The older syntax does not evaluate OUTER JOINs incorrectly. It simply is not capable of expressing the idea of an OUTER JOIN. The lack of a feature is not the same thing as implementing the feature incorrectly.
Larry Lustig
Both Oracle and SQL Server had syntax for expressing outer joins, Oracle used '"+="' or '"=+"' and SQL Server used to use '"*="' or '"=*"' to represent left, and right outer joins, respectively...
Charles Bretana
@Charles, Could you give an example where the old join style is plain wrong?
tuinstoel
@Charles: there is nothing "wrong" with the syntax in the asker's original code sample - it does what it does. Also note that the older ways of doing outer joins in Oracle and SQL Server are *different,* which means *not portable,* which was the point of *my* answer (I'm assuming you were the down-voter).
MusiGenesis
No there are several cases where they are just wrong. I will add examples to my answer...
Charles Bretana
from SQL Server BOL(2000) "In earlier versions of Microsoft® SQL Server™ 2000, left and right outer join conditions were specified in the WHERE clause using the *= and =* operators. In some cases, this syntax results in an ambiguous query that can be interpreted in more than one way."They say themselves that outer joins specified this way don't work properly. And the old outer join syntax has been deprecated. Why are we still arguing about using a syntax that is 17 years out of date?
HLGEM
because too many folks are still using it out of habit and a false belief that they are functionally equivilent.
Charles Bretana
+1  A: 

I have since learned that this is not standard SQL syntax.

That's not quite true. The "a,b where" syntax is from the ansi-89 standard, the "a join b on" syntax is ansi-92. However, the 89 syntax is deprecated, which means you should not use it for new queries.

Also, there are some situations where the older style lacks expressive power, especially with regard to outer joins or complex queries.

It can be a pain going through the where clause trying to pick out join conditions. For anything more than one join the old style is absolute evil. And once you know the new style, you may as well just keep using it.

Joel Coehoorn
Totally agree--especially when your join clauses are more complex than simple equalities.
Philip Kelley
+3  A: 

It really depends on habits, but I have always found Oracle's comma separated syntax more natural. The first reason is that I think using (INNER) JOIN diminishes readability. The second is about flexibility. In the end, a join is a cartesian product by definition. You do not necessarily have to restrict the results based on IDs of both tables. Although very seldom, one might well need cartesian product of two tables. Restricting them based on IDs is just a very reasonable practice, but NOT A RULE. However, if you use JOIN keyword in e.g. SQL Server, it won't let you omit the ON keyword. Suppose you want to create a combination list. You have to do like this:

SELECT *
FROM numbers
JOIN letters
ON 1=1

Apart from that, I find the (+) syntax of Oracle also very reasonable. It is a nice way to say, "Add this record to the resultset too, even if it is null." It is way better than the RIGHT/LEFT JOIN syntax, because in fact there is no left or right! When you want to join 10 tables with several different types of outer joins, it gets confusing which table is on the "left hand side" and which one on the right.

By the way, as a more general comment, I don't think SQL portability exists in the practical world any more. The standard SQL is so poor and the expressiveness of diverse DBMS specific syntax are so often demanded, I don't think 100% portable SQL code is an achievable goal. The most obvious evidence of my observation is the good old row number problemmatic. Just search any forum for "sql row number", including SO, and you will see hundreds of posts asking how it can be achieved in a specific DBMS. Similar and related to that, so is limiting the number of returned rows, for example..

ercan
SQL Server lets you do CROSS JOIN statements. These do not require a following ON clause.
Philip Kelley
I didn't know that, thanks.
ercan
-1: so many errors. Joins increase readability by separating join conditions from resultset predicates. Joins allow for all varieties, including Cross Joins where no On clause is required. Oracle outer join syntax DOES have a left/right, the (+) syntax requires a += or a =+, which is equally difficult to interpret as to "which side" the nulls can be on. The Left Right is not difficult at all, the Left is the stuff you already have the Right is the new table you are Join-(add)ing to the resultset, just as you read, from Left to Right. And the old += syntax is just plain wrong in some cases.
Charles Bretana