asp.netvb.netoracleclientsystem.data.oracleclientora-01036

Constructing a good search query using system.data.oracleclient


I am constructing a search function in a class to be used by several of our asp pages. The idea is simple, take a search term from the user and query the database for the item. Currently I am doing this the wrong way, which is vulnerable to SQL injection attacks (and ELMAH is in there to save the day if something goes wrong):

Public Shared Function SearchByName(ByVal searchterm As String) As DataTable
    SearchByName = New DataTable

    Dim con As New OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings("OracleDB").ConnectionString)



    Try
        con.Open()
        Dim SqlStr As String = "select ID_ELEMENT, ELEMENT_NAME from table_of_elements where upper(ELEMENT_NAME) like upper('%" & searchterm & "%')"
        Dim cmd As New OracleCommand(SqlStr, con)
        SearchByName.Load(cmd.ExecuteReader)





    Catch ex As Exception
        Elmah.ErrorSignal.FromCurrentContext().Raise(ex)

    End Try
    con.Close()
    con.Dispose()




    Return SearchByName
End Function

String concatenation is BAD. Next thing you know, Bobby Tables wrecks my system. Now, the correct way to do this is to to make a proper oracle variable, by putting :searchterm in the string and adding the following line:

cmd.Parameters.Add(New OracleParameter("SEARCHTERM", searchterm))

The problem is since I am using a like statement, I need to be able to have % on either side of the search word, and I can't seem to do that with '%:searchterm%', it just gives an error of ORA-01036: illegal variable name/number.

Can I parameterize but still have my flexible like statement be a part of it?


Solution

  • Instead of doing the concatenation in your VB code, do the concatenation in the SQL statement. Then what you're trying to do should work. Here's some SQL illustrating what I'm talking about:

    select ID_ELEMENT, ELEMENT_NAME 
    from table_of_elements 
    where upper(ELEMENT_NAME) like ('%' || upper(:searchterm) || '%')
    

    BTW, you might end up with more efficient queries if you switch the collation on ELEMENT_NAME to case-insensitive and then remove the calls to upper().