Well, let me give you an example, why it pays to rather be strict about this:
Assume you have a database with products and the main product record has optional info on its origin country (it may only be relavant for food products, for example).
Assume you solve this by making product.origincountryid NULLable.
If you join products and the origin countres, you do an outer join of the countries, as they may or may not be referred:
Code:
SELECT * FROM products prd LEFT JOIN origincountries oc ON oc.id = prd.origincountryid
In itself that already is a case where a cross join would fail listing any products without origin countries, if you do:
Code:
SELECT * FROM products prd, origincountries oc WHERE oc.id = prd.origincountryid
You might fix it with
Code:
SELECT * FROM products prd, origincountries oc WHERE oc.id = prd.origincountryid OR prd.origincountryid IS NULL
That may already convince you to using join conditions rather than WHERE in case you want an outer join. It may not convince enough in an inner join situation. I haven't tried, but in fact it makes no condition on oc in case prd.origincountryid IS NULL, so it may join all origin countries to such products instead of none. That may even differ from database to database.
Now comes a time your data moves to SQL Server and your customer wants to keep the VFP advantage of the DELETED() status of records to be able to recall them.
Now you're quite bitten, as you can't simply SET DELETED ON and let the sql engine care for deleted records. Indeed you have to introduce a deleted bit field in all tables in SQL Server (or other server databases not knowing a deletion flag)
How does this affect all your queries? Adding AND deleted=0 into the where clauses? For every table in the FROM list? As said this turns every outer into an inner join. You will have a hard time adding all OR NULL clauses to compensate this.
The simple solution is being straight forward with the strict rules: If you think about it deleted=0 is not a filter condition as you might think first. It's a condition for joining data you normally never need to think about, as you can only join existing records anyway, but indeed joining further tables ON table.deleted=0 is keeping out deleted records from joining and is keeping the left/right/outer/inner join type intact.
So our product query becomes simpler without misusing the WHERE clause in this way:
Code:
SELECT * FROM products prd LEFT JOIN origincountries oc ON oc.id = prd.origincountryid AND oc.deleted=0 WHERE prd.deleted=0
The only deleted=0 condition to put into the where clause is the condition on the main table you start selecting from. You can't put the prd.deleted=0 into the join condition, too. That would only prevent the join of origin countries to deleted products, but not remove deleted products from the result. That's the only thing to consider and a bit more complicated about it, the deleted=0 condition IS a filter condition for the main table of a query, but it's a join condition for any further joined table.
Since I have to do with such databases I am more rigid about such rules, as it helps preventing errors. The price it comes with is low and if it gets to performance optimizations all dirty tricks off that ideal route can be chosen, but don't do something in the prospect of it becoming machine optimized one day.
Let me think about how to solve that without direct join condition:
Code:
SELECT * FROM products prd, origincountries oc WHERE ((oc.id = prd.origincountryid AND oc.deleted=0) OR prd.origincountryid IS NULL) AND prd.deleted=0
Really? What about more joins, then?
In case of an inner join you can go with
Code:
SELECT * FROM products prd, origincountries oc WHERE oc.id = prd.origincountryid AND oc.deleted=0 AND prd.deleted=0
Yes, that's possible and again a bit shorter to write and might be optimized better by some sql engines, if it becomes more joins and the join order plays a role. But do you really want to think about every query you need to amend? If you find the recipe of making the extra deleted=0 checks in all join conditions you do so and don't have to think about the join types. You can even make it a full or at least half way automated process to change all queries of your application.
Keeping conditions apart from each other in their real meaning makes it easier to maintain and expand queries. That does not only apply to such a big impact of adding a deleted flag to all tables of a database in a real database server.
Bye, Olaf.