代码之家  ›  专栏  ›  技术社区  ›  David Austin

在动态SQL语句中使用like和通配符时出现问题

  •  0
  • David Austin  · 技术社区  · 6 年前

    我试图在存储过程中使用动态SQL语句,根据用户的输入过滤查询。我从一个需要在数据库中找到匹配的名字的参数开始使用basic。

    CREATE PROCEDURE dbo.uspFilter
        @FirstName varchar(100) = null,
        @Debug bit = 1
    AS
    
    DECLARE @SQL nvarchar(max);
    DECLARE @Params nvarchar(max);
    DECLARE @Search nvarchar(300);
    
    SELECT @Params = N'@FirstName varchar(300) = null'
    SELECT @SQL = N'SELECT * FROM Table WHERE 1=1'
    
    IF @FirstName IS NOT NULL
        SELECT @Search = N'@FirstName' + N'%'''
        SELECT @SQL = @SQL + N' AND Forename LIKE ''' + @Search
    
    IF @Debug = 1
        @PRINT @SQL
    
    EXEC sp_executeSQL @SQL, @Params, @FirstName = @FirstName;
    GO
    
    EXEC dbo.uspFilter @FirstName = 'Test', @Debug = 1;
    GO
    

    debug语句的输出看起来正确,但未返回任何结果:

    SELECT * FROM Table WHERE 1=1 AND Forename LIKE '@FirstName%'
    

    编辑:这是一个意味着我正在寻找的精简版本-我将使用不同搜索条件的多个参数。

    2 回复  |  直到 6 年前
        1
  •  2
  •   Thom A    6 年前

    您需要这样做:

    CREATE PROCEDURE dbo.uspFilter
        @Search varchar(300) = null,
        @Debug bit = 1
    AS
    
    DECLARE @SQL nvarchar(max);
    DECLARE @Params nvarchar(max);
    
    SELECT @Params = N'@FirstName varchar(300)';
    SELECT @SQL = N'SELECT * FROM [Table]';
    
    IF @FirstName IS NOT NULL BEGIN
        SET @SQL = @SQL + N' WHERE Forename LIKE @FirstName + ''%'';';
    END ELSE BEGIN
        SET @SQL = @SQL + N';';
    END
    
    IF @Debug = 1
        PRINT @SQL;
    
    EXEC sp_executeSQL @SQL, @Params, @FirstName = @Search;
    GO
    
    EXEC dbo.uspFilter @Search = 'Steve', @Debug = 1;
    

    请注意,尽管Crowcoder关于SQL注入的评论很重要,但您可以编写不允许注入的动态SQL。如上文所述。

    编辑:几处轻微更正。

        2
  •  -1
  •   Sandip - Frontend Developer    6 年前

    您也可以应用下面的动态where条件,而无需进行动态查询,请查看下面的示例。您可以通过以下示例应用AND where子句来连接其他筛选器。

    Declare @firstName VARCHAR(50)='sa'
    
    SELECT
        *
    FROM Table 
    WHERE 
    (
        (Forename LIKE '%'+@firstName+'%' AND @firstName!='') 
        OR 
        (@firstName='')
    )