Using LIKE and % in a stored procedure with parame

2019-03-02 01:51发布

问题:

I am creating a web page to host a database.

I want this web page to have a search box feature that can update a GridView in visual studio 2017 for tables in SSMS 2014.

I want this GrideView to be dynamic in that a end user could select a table, a column, and then specify a "searchString" to apply to the data in the column.

The web page looks like this:

On to the code.

On the search button click event I want the values in each of the three text boxes to be passed into a stored procedure.

Here is the current code for the button click event.

protected void btnSearch_Click(object sender, EventArgs e)
{
    using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["CID1ConnectionString"].ConnectionString))
    {
        SqlDataAdapter searchAdapter = new SqlDataAdapter("Search", con);
        searchAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
        searchAdapter.SelectCommand.Parameters.AddWithValue("@TableName", TableSearchBox.Text.Trim());   // passing text in first text box in
        searchAdapter.SelectCommand.Parameters.AddWithValue("@columnSpecifier", ColumnSearchBox.Text.Trim());   // passing text in second text box in
        searchAdapter.SelectCommand.Parameters.AddWithValue("@searchString", searchStringBox.Text.Trim());   // passing text in third text box in

        DataTable temptable = new DataTable(); //table to have data that satisfies searchString copied to
        searchAdapter.Fill(temptable); //filling table from adapter

        tableDisplay.DataSource = temptable;
        //tableDisplay.Columns[0].Visible = false;
        tableDisplay.DataBind();//bind step
    }
}

Here is my current stored procedure:

ALTER PROCEDURE dbo.Search 
    (@tableName NVARCHAR(50),
     @columnSpecifier NVARCHAR(50),
     @searchString NVARCHAR(50)) 
AS 
     EXEC('SELECT * FROM ' + @tableName + ' WHERE ' + @columnSpecifier + ' LIKE '' + @searchString + %''')

Which is supposed to achieve a query similar to this if the end user populated the first text box with "Basic_Info", the second text box with "Name", and the final text box with "M".

SELECT Name 
FROM Basic_Info 
WHERE Name LIKE 'M%'

It appears since I am using a dynamic table name in the FROM clause I need to use dynamic SQL. I have put my query in an EXEC block and surrounded my SQL syntax with single quotes ('). These single quotes appear to make using the % operator in my LIKE clause impossible but maybe I'm just not seeing it.

Is there a way of achieving this functionality? Should I back up and do this another way? I have read that this might cause SQL injection which sounds like something to be avoided. Any advice is appreciated even about this post and its format. This is my first question on stack overflow!

EDIT: Turns out the stored procedure and parameter use is unnecessary. My final button click event looks like this and just gets the textbox text value to fill out the query.

        protected void btnSearch_Click(object sender, EventArgs e)
    {
            using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["CID1ConnectionString"].ConnectionString))
            {
            DataTable temptable = new DataTable(); //table to have data that satisfies searchString copied to
            SqlDataAdapter searchAdapter = new SqlDataAdapter("SELECT * FROM " + TableSearchBox.Text.Trim() + " WHERE " + ColumnSearchBox.Text.Trim() + " LIKE '"  + searchStringBox.Text.Trim() + "%'", con);
            searchAdapter.Fill(temptable); //filling table from adapter
            tableDisplay.DataSource = temptable;
            tableDisplay.DataBind();//bind step
            }
    }

回答1:

Here's a parameterized dynamic SQL example, using QUOTENAME for identifiers:

CREATE PROCEDURE dbo.Search
    @tableName sysname,
    @columnSpecifier sysname,
    @searchString nvarchar(50)
AS
DECLARE @SQL nvarchar(MAX);
SET @SQL = N'SELECT * FROM ' + QUOTENAME(@tableName) + N' WHERE ' + QUOTENAME(@columnSpecifier) + N' LIKE @searchString + ''%'';';
EXEC sp_executesql
      @SQL
    , N'@searchString nvarchar(50)'
    , @searchString = @searchString;
GO

I suggest one generally avoid AddWithValue because it infers the SQL database type from the provided .NET type. Although this isn't a concern here because you are using a stored procedure and System.String maps to SQL Server nvarchar, it is best to specify the desired SqlDbType and length (or precision and scale) explicitly. Below is one method to do that.

searchAdapter.SelectCommand.Parameters.Add("@TableName", SqlDbType.NVarChar, 128).Value = TableSearchBox.Text.Trim());   // passing text in first text box in
searchAdapter.SelectCommand.Parameters.Add("@columnSpecifier", SqlDbType.NVarChar, 128).Value = ColumnSearchBox.Text.Trim());   // passing text in second text box in
searchAdapter.SelectCommand.Parameters.Add("@searchString", SqlDbType.NVarChar, 50).Value = searchStringBox.Text.Trim());   // passing text in third text box in