Apologies; I somehow missed the reply. Better late than never, I suppose.
Well, I wouldn't even write that WHERE clause in Access with a Jet
back end -- it won't use indexes, so I'd instead use BETWEEN
#1/1/1992# and #12/31/1992#. That won't cause a table scan when sent
to a server, either.
Well, my point was basically that it's easy to make mistakes in writing
queries that would cause unneeded evaluations and make extra mistake of
blaming Access for what was my own mistake. You are correct that the
Year() would be a poor way to find all dates within single year, but
this does not mean we shouldn't use functions at all, especially if we
can keep the function to one side of the expression and the indexed
column on the other side. Furthermore, don't forget that even with a
Year(..) = 1992, the table scan is done on server's side, whereas
Year(..) = '1992' forces table scan on client's side which is always slower.
I think that once a serrer back end is in the mix, the skill level
has already exceeded that of the novice/intermediate Access user. I
know that Microsoft would like to think that's not the case, but it
is, so far as I can see.
Unfortunately, my experience has been that it's too easy to link tables
to ODBC sources and many people posts questions about why their queries
aren't working the way and most of them has never read the whitepaper on
Jet/ODBC connectivity.
I think their response would be "stored procedure", but, of course,
that can't be bound to a form/report.
Well, when using ADO, we can indeed bind the resultset of stored
procedure to a form and still have it updatable, providing we follow
same set of rules we have to follow for writing queries for a form's
recordsource (e.g. one-one correspondence between a row in the resultset
of a sproc and the base table). With reports, it's not as big concern
because we don't really need updatability.
The whole ADO thing in Access was never very successfully
implemented. There are just too many cases where you think you might
get an ADO recordset but instead get a DAO one. Now, that doesn't
upset *me*, because I don't *want* ADO recordsets, but for those who
want to use the capabilities of ADO, it can cause real frustration.
Hmmm, I find it hard to believe we would get a DAO object when we
expected ADO object. While several Access objects indeed support both
DAO and ADO recordsets, it's fairly consistent in what model it actually
uses. Anything you create via Access UI is going to be a DAO object. In
VBA, you could create either DAO or ADO object and bind it to the form.
It's only in the case where you've bound a form to ADO recordset would
you get a ADO recordset from the form's recordset. That's usually
specific enough so I think the behavior is fairly consistent.
But again, I can't think of situations where:
1. you've written good index-using criteria,
As mentioned you still can use functions and indexes, provided you keep
function evaluations on one side and the indexed column on the other
side of evaluation.
An example is when we want to get all records from a many-side table
based on a say, MAX() value from another table.
WHERE AColumn > (SELECT MAX(OtherColumn) FROM OtherTable)
This of course assumes the both original and other table are on the
backend. There also may be differences in how backend optimizes the
query and we want to capitalize on this to help the query run efficient
as possible so there may be cases where it's preferable to use backend's
version of functions even though it may be supported & understood by
Jet/ODBC.
2. it can't be done by simply applying your WHERE clause to the
passthrough itself, e.g.:
SELECT MyPassThrough.* FROM MyPassThrough WHERE ...
There seems to me to be little advantage to having parameters
defined in the passthrough query itself -- if you want the "joy" of
parameters, you can easily define them in the SELECT statement
above, and Jet will process them efficiently *so long as you've
followed rule #1*.
Hmm. Interesting idea. I actually never though to overlay a parameter
query on top of a passthrough query, but that's two objects for one
function, and I'm loath to create several objects. This could get messy
pretty fast enough, even if the performance difference was minimal.
Thanks for the idea, though.
Again, it seems to me that most passthroughs are just client-side
views, and properly ought to be views on the server in the first
place. Is see the role of passthroughs and views as efficiently
processing a SELECT for consumption by the client application(s).
Criteria applied to that results should be easily handled by Jet
passing it off to the server.
Good point. I've found that I seldom use passthrough queries, more
likely to write regular queries referencing linked tables or using VBA
to execute SQL. This may be merely a consequence of the fact that
passthrough are by definition nonupdatable which renders them useless
for vast majority of possible applications within forms, though they may
be of some use for reports where updatability is a moot point.
I do agree with you that in principle, most of processing should stay on
server-side, but I think the way Access works runs counter to that
ideal. We have to write SQL query to build a recordsource to bind forms
to, and we can't rely on stored procedures unless we do it in VBA & ADO,
adding more development work/time, and views are not always the right
answer. For instance, we may still want to add extra conditions at the
runtime rather than at the time we create the views, and views can't
take in parameters, so we need to use a stored procedure anyway if we
need to use parameters).
Until Microsoft make it easier to refer to stored procedures & passing
in parameters without using VBA to set everything, I think the Access's
paradigm will continue to be in conflict with the ideal of keeping
server-side processing on server among other things.
Banana said:
Indeed, for most of cases, we can do just as well with good plain
old saved parameter queries or WhereCondition, as you said, Jet is
good at handing off the Where component. Of course, we have to be
very careful with how we phrase the part. For example:
WHERE Year(SomeDate) = '1992'
Would force a client-side evaluation because Year() function
expects a numeric argument, not a string argument.
Well, I wouldn't even write that WHERE clause in Access with a Jet
back end -- it won't use indexes, so I'd instead use BETWEEN
#1/1/1992# and #12/31/1992#. That won't cause a table scan when sent
to a server, either.
There's really no indication
that client-side evaluation will be done until we go to the server
and look at the log and noticing that Jet is requesting for two
columns, the key and the "SomeData" column but there's no Year
function being passed via ODBC even though ODBC can understand and
pass the Year() to backend.
To me, anything that won't use an index in Access is something you
won't want to send to a server. And this follows one of the
principles I've been using in designing Access apps for a long time:
If you design an efficient Access/Jet app, it will upsize easily,
because the same things that make for an efficient client/server app
also make an Access/Jet app more efficient.
Since there's no clear indication inside the Access environment, I
can easily see how many people would write queries that would
force unnecessary evaluation and never knowing about it until one
day users complain of it being too slow.
I think that once a serrer back end is in the mix, the skill level
has already exceeded that of the novice/intermediate Access user. I
know that Microsoft would like to think that's not the case, but it
is, so far as I can see.
I really, really wish that Microsoft would wise up and enable
support for parameters inside pass-through queries, which would
also facilicate us to use the server's native functions. We can
pass in few of SQL functions and use Jet's functions for the
SELECT clause with no ill effect, but it's a guessing game,
really. I'd rather not guess.
I think their response would be "stored procedure", but, of course,
that can't be bound to a form/report.
Then
when we consider the fact that ADO can provide us with updatable,
bind-able recordset using native SQL dialect, I don't see why
Microsoft can't implement it via the UI as well. C'est la vie.
The whole ADO thing in Access was never very successfully
implemented. There are just too many cases where you think you might
get an ADO recordset but instead get a DAO one. Now, that doesn't
upset *me*, because I don't *want* ADO recordsets, but for those who
want to use the capabilities of ADO, it can cause real frustration.
Well, I know that it's possible to pass multiple statements in a
single passthrough query, providing that multiple statements is
supported & enabled by the backend & the ODBC driver. That said
(and without testing), we'd still have to paste in the literal
values because if the parameters aren't given a default value, we
get an error, and we certainly won't get that little parameter
input box.
Yes, I guess so.
But again, I can't think of situations where:
1. you've written good index-using criteria,
AND
2. it can't be done by simply applying your WHERE clause to the
passthrough itself, e.g.:
SELECT MyPassThrough.* FROM MyPassThrough WHERE ...
There seems to me to be little advantage to having parameters
defined in the passthrough query itself -- if you want the "joy" of
parameters, you can easily define them in the SELECT statement
above, and Jet will process them efficiently *so long as you've
followed rule #1*.
Off the top of my head, I would say by far the best justification
would be the ability to use server's native functions that is not
available in Jet.
Examples of those would be....?
Again, it seems to me that most passthroughs are just client-side
views, and properly ought to be views on the server in the first
place. Is see the role of passthroughs and views as efficiently
processing a SELECT for consumption by the client application(s).
Criteria applied to that results should be easily handled by Jet
passing it off to the server.
The only disadvantage of views, of course, is that you have to link
to them lika a table if you want maximum ease of use. Another
approach, though, would be to create a saved QueryDef with connect
string that returns the rows of the server-side view, but at that
point, you've perhaps written almost as much SQL as it would take to
create the passthrough.
But I'd still vote for most passthroughs belong as views on the
server, regardless of ease of use issues in compared to the
passthrough. My reason is simply that it's better to have
server-side processing defined *server-side* insofar as that is
possible. Putting that same SQL in the application front end seems
to me to be a problematic thing to do.
[]
But I'm just glad that there's a way to avoid rewriting saved
querydef. I can only hope Microsoft eventually get around to fix
the shortcomings with the passthrough queries.
I think passthroughs are mostly of use to those who don't have
administrative permissions on the server, or for use with servers
that don't have views (e.g., MySQL before version 5).