数据库名称为变量 - 存储过程内的动态SQL

时间:2015-08-21 16:42:31

标签: sql-server database variables dynamic

我很难解决这个问题。我的项目要求需要能够使用数据库名称作为参数。我认为这很容易,因为在存储过程中,我们可以像[dbname].[dbo].tblname一样使用它。但是当我用变量替换dbname时,它不起作用。

所以经过一段时间的谷歌搜索,我决定在存储过程中使用动态SQL。但是,目前我很难调试这部分。在我的程序上它引发语法错误。我希望有人能给我一个暗示,或者更好地了解我的项目。提前谢谢!

  SELECT @DBName=DBName FROM Client WHERE ClientCode = @ClientCode

  DECLARE @SQL NVARCHAR(MAX) = N'SELECT * FROM ' + @DBName + 
       N'.[dbo].Users AS A INNER JOIN'+ @DBName  + 
       N'.[dbo].UserRoles AS B On B.RoleCode = A.UserRole INNER JOIN ' + @DBName + 
       N'.[dbo].Branch AS C On C.BranchCode = A.BranchCode WHERE Username= ' + @UserName + 
       N' AND Password = ' + @Password 

  Declare @ParamDefinition AS NVarchar(2000) 
  Set @ParamDefinition =      N'   @ClientCode VARCHAR(20),' +
                              N' @UserName Varchar(15),' +
                              N' @Password NVARCHAR(200)' 

   exec sp_executesql @SQL,@ParamDefinition

3 个答案:

答案 0 :(得分:1)

您在动态SQL生成的第二行缺少空格。

DECLARE @SQL NVARCHAR(MAX) = N'SELECT * FROM ' + @DBName + 
   N'.[dbo].Users AS A INNER JOIN ' + @DBName  + -- space added
   N'.[dbo].UserRoles AS B On B.RoleCode = A.UserRole INNER JOIN ' + @DBName + 
   N'.[dbo].Branch AS C On C.BranchCode = A.BranchCode WHERE Username= ' + @UserName + 
   N' AND Password = ' + @Password 

答案 1 :(得分:1)

  • 在动态SQL中使用QUOTENAME,这对于防止SQL注入非常重要
  • 用户名和密码可以应该保留参数
  • 传递声明的参数

所以这样:

DECLARE @SQL NVARCHAR(MAX) = N'SELECT * FROM ' + QUOTENAME(@DBName) + 
       N'.[dbo].Users AS A INNER JOIN '+ QUOTENAME(@DBName)  +  
       N'.[dbo].UserRoles AS B On B.RoleCode = A.UserRole INNER JOIN ' + QUOTENAME(@DBName) + 
       N'.[dbo].Branch AS C On C.BranchCode = A.BranchCode WHERE Username= @UserName AND Password = @Password'

   exec sp_executesql @SQL, N'@UserName VARCHAR(15), @Password NVARCHAR(200)', @UserName, @Password

最后:永远不要在数据库中存储密码。请改为使用salted hash

答案 2 :(得分:0)

我这样重写,所以很容易阅读

Set @EndDate=Dateadd(DAY,@DaysToAdd,@FromDate) +
Cast(((
         CASE WHEN 5 <= DATEPART(weekday, @FromDate)%7 
        THEN 5
         ELSE 
         DATEPART(weekday, @FromDate)%7
         END)
      -1 + @DaysToAdd )/5 
 as int) 
* 2 - 
   (Case when DAtepart(weekday, @FromDate)=6 then 1 else 0 end) 
和Joe R说的一样,是一个缺失的空间。