【问题标题】:SQL Declare VariablesSQL 声明变量
【发布时间】:2012-02-23 05:31:03
【问题描述】:

任何人都可以检查我的声明...

DECLARE @tblName varchar(MAX), 
        @strSQL varchar(MAX)

SET @tblName ='SELECT DISTINCT o.name as TableName 
                 FROM sysobjects o 
                 JOIN sysindexes x on o.id = x.id  
                WHERE o.name LIKE ''%empty%'''  

SET @strSQL = 'INSERT INTO @tblName VALUES(''trylng'', ''1'')'
EXEC (@strSQL)

我的错误是……

消息 1087,第 15 级,状态 2,第 1 行
必须声明表变量“@tblName”。

【问题讨论】:

  • 我希望返回的表中只有两列,并且数据类型匹配...
  • @OMGPonies:当然,您是指可插入的列。

标签: sql sql-server tsql variables


【解决方案1】:

您的 @tblName 属性存在于外部范围 - 您的“正常”代码行的范围 - 但不存在于您在字符串中构建的 SQL 的内部范围......

你需要将你的行改为阅读:

SET @strSQL = 'INSERT INTO ' + @tblName + ' VALUES(''trylng'', ''1'')'

然后它应该可以正常工作了。

此外,您没有提及您的 SQL Server 版本 - 但从 SQL Server 2005 或更高版本开始,您应该停止使用 sysobjectssysindexes - 相反,使用包含或多或少的新 sys 架构相同的信息 - 但更容易获得。将您的查询更改为:

SET @tblName ='SELECT DISTINCT t.name as TableName 
               FROM sys.tables t
               INNER JOIN sys.indexes i on i.object_id = t.object_id  
               WHERE t.name LIKE ''%empty%'''  

请参阅 MSDN: Querying the SQL Server System Catalog,了解更多关于新 sys 架构中可用内容以及如何充分利用它的信息!

正如“rsbarro”所指出的:把这个 SQL 语句放在引号里很奇怪——你是否也在使用EXEC(...) 执行这个语句??但是,如何将值分配回@tblName 属性?真的没有意义.....

如果你想实际运行这个查询来获取一个值,你应该有这样的东西:

 SELECT TOP 1 @tblName = t.name
 FROM sys.tables t
 INNER JOIN sys.indexes i on i.object_id = t.object_id  
 WHERE t.name LIKE '%empty%'

您需要有一个TOP 1 才能确定 只获得一个值 - 否则此语句可能会失败(如果选择了多行)。

【讨论】:

  • 我错过了什么吗?为什么@tblName 用单引号括起来?那不就是把它设置成字符串,而不是表名吗?
  • 不,我的意思是第二个陈述。不应该是不带引号的SET @tblName = SELECT DISTINCT t.name... 吗? @strSQL 的编写方式将具有 INSERT INTO SELECT DISTINCT t.Name as TableName... 的值。在我看来,这将是无效的,不是吗?
  • @rsbarro:嗯,好吧——好吧,不确定——我假设 OP 也将使用EXEC(....) 执行该 SQL 语句。如果不是 - 那么你是绝对正确的,它不会工作!
  • 酷。我已经很晚了,我以为我要么看到了一些新语法,要么失去了理智... =]
  • 另一个问题...为什么我们需要使用连接到 SYS.INDEXES,因为与我们的“WHERE”匹配的表列表在 SYS.TABLES 中......??
【解决方案2】:

不确定你到底想要做什么,但我认为你想要这样的东西:

DECLARE @tblName varchar(MAX), @strSQL varchar(MAX)
SET @tblName = 
    (select distinct o.name as TableName 
     from sysobjects o 
     join sysindexes x on o.id = x.id  
     where o.name LIKE '%empty%')
SET @strSQL = 'INSERT INTO [' + @tblName + '] VALUES(''trylng'', ''1'')'
exec (@strSQL)

话虽如此,这里仍有几件事需要注意。您需要处理SELECT DISTINCT 返回除单个记录之外的任何内容的情况。另外,当@tblName 始终具有相同的值时(因为WHERE 子句中没有使用任何变量),我并不真正理解构建动态SQL(在@strSQL 中)的必要性。

【讨论】:

  • +1,只有一个注意事项:通常将名称合并到像这样的动态脚本中更安全:'INSERT INTO ' + QUOTENAME(@tblName) + '…',而不是简单地在它们周围加上方括号。
猜你喜欢
  • 1970-01-01
  • 2012-03-13
  • 2015-05-04
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多