2015-03-02 110 views
-5

我试图使用存储过程创建一个已过滤索引。但是,当代码写入存储过程时没有错误显示,但是当我运行查询时,它无法检测到FirstName参数。如何在存储过程中创建过滤索引(SQL Server)

名字从BorrowerPersonal表

CardNumber从BorrowerCard表

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER PROCEDURE [dbo].[BorrowerCardG11Match] 

@CardNo VARCHAR(20), 
@FirstName VARCHAR(30) 

AS 
BEGIN 
DECLARE @SQL NVARCHAR(Max) 
SET @CardNo = 17522 
SET @FirstName = 'Simon' 

     SET @SQL = N'SELECT dbo.BorrowerCard.BorrowerCardID 
      FROM dbo.BorrowerCard 
      INNER JOIN dbo.BorrowerPersonal 
      ON dbo.BorrowerPersonal.BorrowerPersonalID = BorrowerCard.BorrowerPersonalID 
      WHERE CardNumber =' + CAST(@CardNo AS VARCHAR(20)) 
      SET @SQL += 'AND NameFirst = ' + CAST(@FirstName AS VARCHAR(30)) 

        EXECUTE sys.sp_executesql @SQL 
END 
+3

这似乎并不具有任何与创建过滤索引... – 2015-03-02 12:26:15

+2

有一些理由使用动态SQL,这不是在这个问题吗?因为这是您应该使用静态SQL的场景的主要示例。正如所写的,这个过程是一个等待发生的SQL注入攻击。 – Allan 2015-03-02 12:28:53

+0

如果您提出包含代码的问题:请不要更改代码,否则答案将无效。 (你只是试着编辑一个答案,所以这段代码适用于你的新问题,这不是这样做的,只是不要改变你的问题!) – knedlsepp 2015-03-02 14:39:53

回答

-1

您有几个错误。这是你将用当前的声明得到的。

SELECT dbo.Details.ID 
      FROM dbo.Details 
      INNER JOIN dbo.Personal 
      ON dbo.Personal.ID = Details.ID 
      WHERE Number =17522AND Name = Simon 

如果您在执行查询之前添加PRINT @SQL,您可以看到它。

  1. 添加空间之前,并在'AND Name ='
  2. 添加额外的报价轮命名

虽然第一是不是一个语法错误,但糟糕的格式化第二个实际上是一个错误,因为这将是认为专栏不是价值'西蒙'。 试试这个:

SET @SQL = N'SELECT dbo.Details.ID 
     FROM dbo.Details 
     INNER JOIN dbo.Personal 
     ON dbo.Personal.ID = Details.ID 
     WHERE Number =' + '''' + @No + '''' + 
       ' AND Name = N' + '''' + @First + '''' 
+0

@Allan,正确 – 2015-03-02 12:39:40

+1

危险。 SQL注入。 – 2015-03-03 19:32:22

2

尽管现有的答案(如Giorgi的Nakeuri的)显示,使动态SQL的工作方式,如规定的问题,没有理由使用动态SQL摆在首位。除非有更多的这个程序不是已经提交,解决这个问题的最好的办法是使用静态SQL它重新写:

ALTER PROCEDURE [dbo].[BorrowerCardG11Match] 

@No VARCHAR(20), 
@First VARCHAR(30) 

AS 
BEGIN 
SET @No = 17522 
SET @First = 'Simon' 

      SELECT dbo.Details.ID 
      FROM dbo.Details 
      INNER JOIN dbo.Personal 
      ON dbo.Personal.ID 
       = Details.ID 
      WHERE Number = @No 
       AND First = @Name 

END 

如果你不能做到这一点,你会更好的结合这两个变量你有,而不是它们串联:

ALTER PROCEDURE [dbo].[BorrowerCardG11Match] 

@No VARCHAR(20), 
@Name VARCHAR(30) 

AS 
BEGIN 
DECLARE @SQL NVARCHAR(Max) 
DECLARE @SQLParams NVARCHAR(Max) 
SET @No = 17522 
SET @First = 'Simon' 

     SET @SQL = N'SELECT dbo.Details.ID 
      FROM dbo.Details 
      INNER JOIN dbo.Personal 
      ON dbo.Personal.ID 
       = Details.ID 
      WHERE Number = @No 
       AND Name = @First' 
     SET @SQLParams = N'@No varchar(20), @First varchar(30)' 

     EXECUTE sys.sp_executesql @SQL, SQLParams, 
            @[email protected], @[email protected] 
END 

这些解决方案阻止你不必置单引号和防止SQL注入攻击。

-1

sql server 2012可以使用concat -

set @SQL = concat('SELECT dbo.Details.ID 
      FROM dbo.Details 
      INNER JOIN dbo.Personal 
      ON dbo.Personal.ID 
       = Details.ID 
      WHERE Number =''' ,@No,'''',' AND Name = ''',@First,'''') 
+0

危险。 SQL注入。 – 2015-03-03 19:32:29

+0

请解释你的答案? – 2015-03-03 19:39:09

+0

咦?我没有答案,因为[艾伦已经给了一个更好的](http://stackoverflow.com/a/28810191/61305)。 – 2015-03-03 19:42:34

相关问题