views:

1293

answers:

6

Hi all,

[Update: The query works if I hardcode in the parameters - so it has to do with the way I am adding parameters to the query]

For the life of me, I cannot figure out what the problem is here.

Here is the query being passed to the datareader:

    SELECT * FROM (SELECT TOP ? StartDate, [ID] FROM
    (SELECT TOP ? StartDate, [ID] FROM Story 
    ORDER BY StartDate DESC, [ID] DESC) AS foo 
    ORDER BY StartDate ASC, [ID] ASC) AS bar 
    INNER JOIN Story AS t ON bar.ID = t.ID 
    ORDER BY bar.StartDate DESC, bar.[ID] DESC

The parameters are added in the following order:

var pNumToRetrieve = new OleDbParameter("", OleDbType.Integer) {Value = numToGet};
var pResultSet = new OleDbParameter("", OleDbType.Integer) {Value = resultSet};

_cmd.Parameters.Add(pNumToRetrieve);
_cmd.Parameters.Add(pResultSet);

If I enter this query into access directly it works just fine. However, when running the query from ASP.NET, I get the following error:

The SELECT statement includes a reserved word or an argument name that is misspelled or missing, or the punctuation is incorrect.

What am I doing wrong?

Thanks,

Adam

A: 

I notice that not all of your ID columns have square braces around them. This could be it but it's been a while since I've played with Access so someone else may have a better answer.

EDIT:

As you've had no luck so far I'll attempt another guess. Could you try changing the "*" to instead explicitly name the columns you want.

FINAL EDIT:

The last piece of advice I have to offer is to replace the query with a very simple version of itself that produces no results. Then give it a test, if it fails it must be the parameter code that is failing, if not then it's something in the complexity of the query. If you gradually reconstruct the query you should then be able to detect the fail point. Sorry I can't be more help though.

Chris Simpson
Hi Chris,I added the brackets just to make sure that ID was not a reserved word in Access. Same result without them.Thanks -- Adam
adamisnt
Never mind. Hope one of the other answers helps
Chris Simpson
Same result as before. Thanks for you help, Chris.
adamisnt
I appreciate your ideas - See the update I posted above. If I hard-code the parameter values into the query, it works fine. So it must have to do with the way I am declaring/adding parameters. Thanks -- Adam
adamisnt
A: 

Is it that the pResultSet parameter is typed as OleDbTypeInteger?

Carl Manaster
Hi Carl, I added the type as part of my troubleshooting. Removing the type parameter and passing the value as a generic object yields the same results.Thanks for your help.
adamisnt
A: 

Does it like the order by in the subqueries? That isn't supported in SqlServer.

Edit : My mistake, I missed the Top ?

sgmoore
Hi sgmoore,The query is one I found at http://www.codeproject.com/KB/aspnet/paging_various_databases.aspx for paging results. Like I said, entering the query directly in SQL View in Access works perfectly.
adamisnt
How are you generating the command string. if you are using append various strings together, you might be missing a space at the end of a line.
sgmoore
I am appending strings - However, I hardcoded in the parameter values, and the query worked. So I suspect there is a problem in the way I am adding/declaring parameters. I can't find the problem though! Argggh..
adamisnt
Does the parameter name matter or rather lack of a name?eg try OleDbParameter("NumberToGet", OleDbType.Integer)rather than OleDbParameter("", OleDbType.Integer)
sgmoore
Same result when naming the parameters - Thanks
adamisnt
I'm afraid it beats me. This is the stage where I would dump the parameters and instead embed the required values directly into select command. (Should not need to worry about Sql Injection in this case)
sgmoore
A: 

See if changing the query to this way helps.

PARAMETERS numToGet number, rowsToGet numeric;
SELECT * FROM (SELECT TOP numToGet StartDate, [ID] FROM
    (SELECT TOP rowsToGet StartDate, [ID] FROM Story 
    ORDER BY StartDate DESC, [ID] DESC) AS foo 
    ORDER BY StartDate ASC, [ID] ASC) AS bar 
    INNER JOIN Story AS t ON bar.ID = t.ID 
    ORDER BY bar.StartDate DESC, bar.[ID] DESC

EDIT: On a side note, what is the value being passed using those 2 parameters? Are both numbers?

shahkalpesh
Hi shahkalpesh,I get the same result with your query. Thanks -- Adam
adamisnt
Yes, I am passing 10 and 20, in that order
adamisnt
Could you name the parameter when constructing them, using the above query? var pNumToRetrieve = new OleDbParameter("numToGet", OleDbType.Integer) and name the 2nd parameter as well. Does that work?
shahkalpesh
Same result when I name the parameters - Thanks -- Adam
adamisnt
+5  A: 

The N in TOP N queries in Jet SQL cannot be parameterized, period. You have to write your SQL string on the fly to get a variable N. This means either that you can't use a saved QueryDef, or that you have to edit the SQL of the QueryDef and save it before using it.

David-W-Fenton
+1. Good catch. I was so stupid that I didn't try that query first in Access to see if it works :)
shahkalpesh
Well I guess that explains it then :P Thanks for providing the answer! Do you know of a good resource that could help me get up to speed with running Access queries in ASP.NET - specifically, passing parametrized queries via ASP.NET/ADO? I am also running into problems with parametrized BETWEEN queries on Dates as well. Thanks again! -- Adam
adamisnt
"You have to write your SQL string on the fly to get a variable N" -- well, you could re-write it using a different construct e.g. a correlated subquery.
onedaywhen
With Jet/ACE, the correlated subquery may or may not be as efficient as TOP N. It's also much more convoluted SQL.
David-W-Fenton
+2  A: 

Consider rewriting you TOP N constructs using a correlated subqueries.

Here's a simple example. Consider a table named Sequence with a column (seq) of unique INTEGERs (a standard SQL auxiliary table which is useful in countless situations -- every database should have one!)

Both the following queries return two the highest values for seq:

1)

SELECT TOP 2 seq 
  FROM SEQUENCE
 ORDER 
    BY seq DESC;

Pros: The Access database engine performs this relatively well (as you would expect for proprietary syntax). Cons: Proprietary syntax therefore bad for portability. The N (as in TOP N) cannot be parametrized. For me, using DESC in the ORDER BY to return the highest values is counter-intuitive.

2)

SELECT S1.seq 
  FROM SEQUENCE AS S1
 WHERE 2 >= (               
             SELECT COUNT(*)          
              FROM SEQUENCE AS S2       
             WHERE S2.seq >= S1.seq 
            );

Pros: Standard SQL syntax therefore good for portability. The N can be parametrized. Cons: The Access database engine does not optimize correlated subqueries well therefore performance will degrade as the number of rows in the table increases (as ever with performance issues, you will need to test it). Some SQL coders find a correlated subquery hard to understand and therefore has potential maintenance issues.

onedaywhen
I think you have an error: for "SELECT seq AS S1" you mean "SELECT seq".
David-W-Fenton
Good spot! Code executed OK though ;) Now corrected.
onedaywhen
Thanks onedaywhen - it is nice to know that if I *must* use a parametrized query, I can do it this way. Though - this seems a bit harder for my sql/db ignorant mind to grasp. I voted your question up - thanks for your help. --Adam
adamisnt
It's a good answer. Thanks for not editing into my answer...
David-W-Fenton
Te-he -- it's not my answer or yours. This is a collaboration site :)
onedaywhen