【问题标题】:Using LIKE and % in a stored procedure with parameter in FROM clause在 FROM 子句中带有参数的存储过程中使用 LIKE 和 %
【发布时间】:2018-12-24 15:03:06
【问题描述】:

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

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

我希望这个 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 注入,这听起来像是要避免的事情。任何关于这篇文章及其格式的建议都值得赞赏。这是我关于堆栈溢出的第一个问题!

编辑:原来存储过程和参数的使用是不必要的。我的最终按钮单击事件如下所示,只是获取文本框文本值来填写查询。

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

【问题讨论】:

  • 您可能希望转义 searchString - public static string SqlLikeEscape(this string value) { if (string.IsNullOrEmpty(value)) { return value; } return Regex.Replace(value, @"(?<ch>%|_|\[)", @"[${ch}]"); } 否则,例如,您将难以在表中搜索 % 值。
  • 我建议用户使用下拉列表来选择表名和列名。
  • 他们到位了! (虽然标签不好)它们位于每个搜索框的正下方。

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


【解决方案1】:

这是一个参数化的动态 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

【讨论】:

  • 如何从 C# 中调用它? cmd.Parameters.Add("@tableName", SqlDbType. ??? sysname 无法从提供商处获得。
  • @Mary, sysname 是 nvarchar(128) 的别名。我将它用于表名和列名参数,因为这是这些标识符的实际类型。我添加了一个示例和有关避免 AddWithValue 的信息。
  • 感谢您阐明要使用的数据类型。我在查找 sysname 时确实看到了这一点,但我不确定。看到有点版本依赖。加上.AddWithValue.Add 上的优秀博客我一直使用.Add,但我对大小参数松懈。我让海报使用 `.AddWithValue 滑动,因为我很高兴他们至少使用了参数。
猜你喜欢
  • 2010-09-19
  • 1970-01-01
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 2018-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多