在带有FROM子句中参数的存储过程中使用LIKE和%

时间:2018-07-17 02:31:20

标签: c# sql-server visual-studio dynamic-sql

我正在创建一个网页来托管数据库。

我希望此网页具有搜索框功能,可以为Visual Studio 2017中的SSMS 2014中的表更新GridView。

我希望此GrideView是动态的,因为最终用户可以选择一个表,一个列,然后指定一个“ searchString”以应用于列中的数据。

网页如下:

转到代码。

在搜索按钮单击事件上,我希望将三个文本框中的每个值都传递到存储过程中。

这是按钮单击事件的当前代码。

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
    }
}

这是我当前的存储过程:

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

如果最终用户在第一个文本框中填充“ Basic_Info”,第二个文本框填充“ Name”,最后一个文本框填充“ M”,则应该实现与此类似的查询。

SELECT Name 
FROM Basic_Info 
WHERE Name LIKE 'M%'

由于我在FROM子句中使用动态表名,因此出现该信息,因此我需要使用动态SQL。我将查询放在EXEC块中,并将SQL语法用单引号(')引起来。这些单引号似乎无法在我的LIKE子句中使用%运算符,但也许我只是看不到它。

是否有实现此功能的方法?我应该备份并以其他方式执行此操作吗?我读过,这可能会导致SQL注入,这听起来像应该避免的事情。即使是关于此帖子及其格式的任何建议,我们也应感谢。这是我关于堆栈溢出的第一个问题!

EDIT:显示存储过程,不需要使用参数。我的最终按钮单击事件看起来像这样,只是获取文本框文本值来填写查询。

        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 个答案:

答案 0 :(得分:3)

这是一个参数化的动态SQL示例,使用QUOTENAME作为标识符:

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

我建议一般使用avoid AddWithValue,因为它可以从提供的.NET类型推断出SQL数据库类型。尽管这里没有关系,因为您使用的是存储过程,并且System.String映射到SQL Server nvarchar,但是最好显式指定所需的SqlDbType和长度(或精度和小数位数)。下面是执行此操作的一种方法。

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