【问题标题】:Database Name as Variable -Dynamic SQL inside stored procedure数据库名称作为变量 - 存储过程中的动态 SQL
【发布时间】:2015-11-15 16:48:21
【问题描述】:

我很难解决这个问题。我的项目要求需要能够使用数据库名称作为参数。我认为这很容易,因为在存储过程中,我们可以像[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

【问题讨论】:

  • 而不是执行,打印sql,取打印的sql,解析它,如果没有错误,运行它。它会让您更好地了解从哪里开始。
  • 从更简单的开始,例如'@sql = select count(*) records from ' + @DBName + 'dbo.users where 1=2'

标签: sql-server database variables dynamic


【解决方案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】:

您在动态 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 

【讨论】:

    【解决方案3】:

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

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

    就像乔 R 说的那样,是一个缺失的空间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多