4

Update 4

Updated the whole question to reflect my changes. Still Not Working.

This has been annoying me for two days now. I'm updating an old ordering interface system that our customers use, written in ASP Classic, VBScript. It connects to an SQL database on Windows Server 2003.

Stored Procedure

I have a stored procedure that returns a list of pallet codes, filtered by customer ID and searchable by pallet code:

CREATE PROCEDURE dbo.sp_PalletSearch
@CustomerRef        Int,
@SearchQuery        VarChar(15) = '%'
AS

SET NoCount On  
SET @SearchQuery = '%' + COALESCE(@SearchQuery, '%') + '%'

SELECT      p.PalletID,
            p.PalletCode
FROM        dbo.v_PalletSearch p
WHERE       p.CustomerRef   = @CustomerRef
AND         p.PalletCode    LIKE @SearchQuery
ORDER BY    p.PalletCode    ASC

SET NoCount Off
GO

This seems to work fine in SQL Query Analyzer with and without a search term:

exec sp_PalletSearch 100, '' and exec sp_PalletSearch 100, 'PalletCode'

ASP Web Page

So onto the web page itself... This is the ADO Command I use to get the recordset and this is where my problem starts. It just simply will not return anything:

Dim strSearchQuery
strSearchQuery = "PalletCode"

Dim objCmd
Set objCmd = Server.CreateObject("ADODB.Command")
objCmd.ActiveConnection = cConn
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "sp_PalletSearch"
objCmd.Parameters.Append objCmd.CreateParameter("@CustomerRef", adInteger, adParamInput)
objCmd.Parameters.Append objCmd.CreateParameter("@SearchQuery", adVarChar, adParamInput, 15)
objCmd.Parameters("@CustomerRef").Value = CustomerID
objCmd.Parameters("@SearchQuery").Value = strSearchQuery

Dim objRS
Set objRS = objCmd.Execute
Set objCmd = Nothing


Do While Not objRS.EOF
    Response.Write(objRS("PalletID").Name & ": " & objRS("PalletID").Value & " | " & objRS("PalletCode").Name & ": " & objRS("PalletCode").Value & "<br>")
    objRS.MoveNext
Loop
        
objRS.Close
Set objRS = Nothing

I Have Tried...

If I edit this line in my ADO Command:

objCmd.CommandText = "sp_PalletSearch"

And change it to:

objCmd.CommandText = "{call sp_PalletSearch(?, '" & strSearchQuery & "')}"

And remove:

objCmd.CommandType = adCmdStoredProc

All searching works fine. This is what I will stick to if a real solution isn't found.


If I edit the stored procedure to get the pallet code that equals the search term instead of LIKE, and comment out

--SET @SearchQuery = '%' + COALESCE(@SearchQuery, '%') + '%'

then I will get the exact match. This would tell me that the ADO Command is passing the parameters ok. But then why won't the stored procedure get results LIKE the @SearchQuery?


Another thing to note is that replacing the ADO Command with the following works fine with pallet code LIKE. I don't see this snippet as a secure option, please tell me if I'm wrong. I would rather use the parametrised command:

strSQL = "EXECUTE sp_PalletSearch " & CustomerID & ", '" & strSearchQuery & "' "
Set objRS = Server.CreateObject("ADODB.Recordset")
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open cConn
objRS.Open strSQL, objConn  

It's a big ask, but I like to do things efficiently and correctly, and I love to learn. I hope you guys can help me with this puzzle.

Community
  • 1
  • 1
  • [This knowledge base article](http://support.microsoft.com/kb/164485) describes three ways to make stored procedure calls using ADO from VBScript/ASP. See if one of those methods work for you. Maybe try separating your parameter creation from its assignment, for debugging anyway. I would personally assign the name of the SP to `CommandText` prior to adding the params. I don't think it's needed in your case, but if you ever wanted to use `objCmd.Parameters.Refresh()` (as shown in one of the examples), you'll need to assign `CommandText` first, obviously. – Bond Aug 26 '14 at 14:48
  • Thanks for the link. After reading I edited the command to this, using the example in the article but still the same result: [POSTED ABOVE: Update 1] I'll keep playing. – James Winstanley Aug 26 '14 at 15:10
  • `01` is not an `int` SQL data type, did you mean to pass `1`? Also in your update you not assigning to the `Value` property like `cmd.Parameters("@CustomerRef").Value = CustomerID` instead you are replacing the `cmd.Parameters("@CustomerRef")` object with `CustomerID` this is not the same. See [My Answer to Using Stored Procedure in Classical ASP .. execute and get results](http://stackoverflow.com/a/21944948/692942) – user692942 Aug 26 '14 at 15:36
  • @Lankymart Thank you, I have updated my question and code after reading your post. I added the ".Value" and removed the redundant `Set objConn = Server.CreateObject("ADODB.Connection")` Still no luck :( – James Winstanley Aug 26 '14 at 15:54
  • For the first and second tests in your `Update 2` section, get rid of the single quotes around `strSearchQuery` and `?`, respectively. You shouldn't be providing the quotes. You've defined the param as `VarChar`. ADO will take of the quotes. – Bond Aug 26 '14 at 17:08
  • @Bond If you look at `Update 1` you will see that was the first thing I tried. `Update 2` were other attempts at trying to work out this puzzle. – James Winstanley Aug 27 '14 at 06:50
  • As @Bond pointed out do not use `{call }` syntax in your `CommandText` property this is because the `ADODB.Command` builds this itself based on the `CommandType` you use in this case it should be `CommandType = adCmdStoredProc`. – user692942 Aug 27 '14 at 11:32
  • @Lankymart Thanks, I have updated my code to reflect this. Still doesn't solve my issue though. – James Winstanley Aug 27 '14 at 11:40
  • You are positive that `CustomerID` and `strSearchQuery` contain what you expect? Have you tried outputting those values before executing the query just to check? – user692942 Aug 27 '14 at 11:50
  • I am possitive and have outputted both values. They work with exact matches: `p.PalletCode = @SearchQuery`. They won't work with `p.PalletCode LIKE @SearchQuery`. **NOTE:** `SET @SearchQuery = '%' + COALESCE(@SearchQuery, '%') + '%'` – James Winstanley Aug 27 '14 at 11:58
  • Your code works for me. In fact, I couldn't get it _not_ to work. I used it exactly as you have shown (even with the initial `= '%'` assignment and `COALESCE()` function) and that worked. I then removed any `%`'s in the SP and instead passed in the string literal `%text%` to perform the search and that worked. So I think your code is proper. I wonder if it's a driver/provider issue -- maybe the provider being used in your connection string or your ADO version? – Bond Aug 27 '14 at 12:53
  • I want to clarify, though, for you and @Lankymart, I don't see any reason why you couldn't use the `{ call }` syntax. It's a bit unorthodox, but it's a valid way to call a SP from ASP and still use named params. I was just suggesting you remove the single quotes from the second param. You shouldn't need to use them. In other words, use this syntax: `{ call sp_PalletSearch(?,?) }` instead of `{ call sp_PalletSearch(?,'?') }` or `{call sp_PalletSearch(?, '" & strSearchQuery & "')}`. – Bond Aug 27 '14 at 12:56
  • @Bond I realise that but up until today I've never found a use for it that isn't covered by the built-in `CommandType` enums. – user692942 Aug 27 '14 at 12:59
  • @Lankymart Yeah, nor have I. It's crazy that it works with the `{ call }` syntax but not using `adCmdStoredProc` even though we're using the same set of named params. – Bond Aug 27 '14 at 13:02

3 Answers3

1

I think you causing yourself more issues by trying anything and everything. With each attempt you make slight mistakes in your syntax (like quotes in the wrong place, not specifying a CommandType etc).

If it helps this is how I would code for that stored procedure

Dim cmd, rs, sql
Dim data, rows, row

Set cmd = Server.CreateObject("ADODB.Command")
'Name of your stored procedure
sql = "dbo.sp_PalletSearch"

With cmd
  .ActiveConnection = cConn 'Assuming cConn is a connection string variable
  .CommandType = adCmdStoredProc
  .CommandText = sql
  'Define Stored Procedure parameters
  Call .Parameters.Append(.CreateParameter("@CustomerRef", adInteger, adParamInput, 4))
  Call .Parameters.Append(.CreateParameter("@SearchQuery", adVarChar, adParamInput, 15))
  'First parameter is optional so only pass if we have a value, will default to NULL.
  If Len(CustomerId) > 0 Then .Parameters("@CustomerRef").Value = CustomerID
  .Parameters("@SearchQuery").Value = strSearchQuery
  Set rs = .Execute()

  'Populate 2D-Array with data from Recordset
  If Not rs.EOF Then data = rs.GetRows()

  'Close and Release Recordset from memory
  Call rs.Close()
  Set rs = Nothing
End With
Set cmd = Nothing

If IsArray(data) Then
  rows = UBound(data, 2)
  For row = 0 To rows
    Call Response.Write("Pallet Id: " & data(0, row) & " | Pallet Code: " & data(1, row) & "</ br>")
  Next
End If
user692942
  • 16,398
  • 7
  • 76
  • 175
  • Thank you for taking your time to help, but copy & pasting your code (which we both know should work) returns no rows. Again, changing the stored procedure to find exact matches, both your code and mine works a treat. – James Winstanley Aug 27 '14 at 11:54
  • @JamesWinstanley Ok, wait a minute you said something key there... *"changing the stored procedure to find exact matches"* so the code does work, but adding that `LIKE` clause in the stored procedure causes it to stop working? Is that right? – user692942 Aug 27 '14 at 12:04
  • @JamesWinstanley So your trying to do something like `LIKE '%PalletCode%'`? Sorry just want to be clear. – user692942 Aug 27 '14 at 12:07
  • That is correct. (Make sure you have a quick look under the heading **"I Have Tried..."** < That is where it gets confusing. – James Winstanley Aug 27 '14 at 12:08
  • @JamesWinstanley So what does your `strSearchQuery` variable contain when you pass it in? – user692942 Aug 27 '14 at 12:11
  • Ok. A PalletCode of `bww100052` exists in the database. That is the value of `strSearchQuery` I am using to test. – James Winstanley Aug 27 '14 at 12:13
  • @JamesWinstanley I wonder if this could be a database collation issue, have you tried `BWW100052`? – user692942 Aug 27 '14 at 12:16
  • @JamesWinstanley Scrap that read your **I Have Tried...** section properly now... Puzzled to be honest sorry. – user692942 Aug 27 '14 at 12:21
  • 1
    @JamesWinstanley You could try profiling it with SQL Profiler to see what is being passed. – user692942 Aug 27 '14 at 12:23
1

Solved

Thank you to Bond and especially Lankymart for your help. Lankymart, your suggestion to use SQL Profiler helped. My server has the older version I guess - Profiler.

I found this when looking in the Profiler Trace: @SearchQuery = 'bww100052 '

So I decided to force a Trim inside the stored procedure: LTRIM(RTRIM(@SearchQuery))

Stored Procedure

CREATE PROCEDURE dbo.sp_PalletSearch
@CustomerRef        Int,
@SearchQuery        VarChar(15) = '%'
AS    

SET NoCount On  
SET @SearchQuery = '%' + COALESCE(LTRIM(RTRIM(@SearchQuery)), '%') + '%'

SELECT      p.PalletID,
            p.PalletCode
FROM        dbo.v_PalletSearch p
WHERE       p.CustomerRef   = @CustomerRef
AND         p.PalletCode    LIKE @SearchQuery
ORDER BY    p.PalletCode    ASC

SET NoCount Off
GO

ADO Command

Dim objCmd
Set objCmd = Server.CreateObject("ADODB.Command")
objCmd.ActiveConnection = cConn
objCmd.CommandType = adCmdStoredProc
objCmd.CommandText = "sp_PalletSearch"
objCmd.Parameters.Append objCmd.CreateParameter("@CustomerRef", adInteger, adParamInput)
objCmd.Parameters.Append objCmd.CreateParameter("@SearchQuery", adVarChar, adParamInput, 15)
objCmd.Parameters("@CustomerRef").Value = CustomerID
objCmd.Parameters("@SearchQuery").Value = Trim(strSearchQuery)

Dim objRS
Set objRS = objCmd.Execute
Set objCmd = Nothing

Finally

I thought I would never solve this one, it was just making no sense at all! I'll throw a few more tests at it, but it looks like trimming the variable was needed. I don't know why the extra space was added though.

  • Knew it would be something simple that's why I suggested outputting your variables first, something like `Response.Write "'" & strSearchQuery & "'"` would have done the trick. Glad you finally sorted it! – user692942 Aug 27 '14 at 13:29
  • @Lankymart That's the thing. There are no spaces being passed in from the ADO Command. From either `"'" & objCmd.Parameters("@SearchQuery") & "'"` OR `"'" & strSearchQuery & "'"` – James Winstanley Aug 27 '14 at 13:33
  • And it's `varchar(15)` so shouldn't leave any "fixed" space that would only happen if you used `char(15)`...weird. – user692942 Aug 27 '14 at 13:38
  • 2
    @Lankymart I think it's with the literal `15` that's being used in `CreateParameter()`. You could use `Len(strSearchQuery)` instead and it shouldn't pad extra spaces. – Bond Aug 27 '14 at 14:59
  • @Bond That's strange because it's defined as `adVarChar` I do this all the time and so far don't think I've had this issue. But probably safer to do `Len(strSearchQuery)` anyway, good spot. – user692942 Aug 27 '14 at 15:05
  • Yes, that does work, although you will need to add a fallback for zero length. – James Winstanley Aug 27 '14 at 15:14
-1

Try it with

objCmd.Parameters.Append objCmd.CreateParameter("@SearchQuery", adVarChar, adParamInput, 15, "'PalletCode'")

Notice that "'PalletCode'" has an additional set of single quotes inside of it.

user692942
  • 16,398
  • 7
  • 76
  • 175
kaufman
  • 114
  • 1
  • 1
  • [Update 2] I have tried all possible combinations and still nothing get returned. There is something odd happening - Check above Update 2 – James Winstanley Aug 26 '14 at 15:34
  • You don't need the extra quotes `'` that just defines your passing a `varchar` data type as you specify that already in the `CreateParameter()` method it's superfluous. – user692942 Aug 26 '14 at 15:34