2011-08-29 68 views
41
DECLARE @dbName nvarchar(128) = 'myDb' 
DECLARE @siteId int 
exec ('SELECT TOP 1 @siteId = Id FROM ' + @dbName + '..myTbl') 
select @siteId 

当我运行上面的脚本我收到以下错误如何在t-sql中使用'execute'将值设置为变量?

Msg 137, Level 15, State 1, Line 1 
Must declare the scalar variable "@siteId". 

(1 row(s) affected) 

为什么,以及如何解决它?

谢谢

回答

82

您可以将输出参数与sp_executesql一起使用。

DECLARE @dbName nvarchar(128) = 'myDb' 
DECLARE @siteId int 
DECLARE @SQL nvarchar(max) = N'SELECT TOP 1 @siteId = Id FROM ' + quotename(@dbName) + N'..myTbl' 
exec sp_executesql @SQL, N'@siteId int out', @siteId out 
select @siteId 
+1

+1这是更好的方法。我看到一个参数化的数据库名称,并驳回了sp_executesql ... – gbn

+1

+1在创建临时表时没有过热 – garik

20

动态SQL是一个不同的范围外,调用SQL:所以@siteid无法识别

你将不得不使用临时表/表变量的动态外SQL:

DECLARE @dbName nvarchar(128) = 'myDb' 
DECLARE @siteId TABLE (siteid int) 

INSERT @siteId 
exec ('SELECT TOP 1 Id FROM ' + @dbName + '..myTbl') 

select * FROM @siteId 

注:TOP时没有ORDER BY是意义。表格没有自然的,隐含的或内在的顺序。任何订单仅由最外层订购

+0

“没有一个ORDER BY TOP是毫无意义的” - 毫无意义的可能是一个有点强在这里,也许我要的是1个纪录,我都不在乎,我应该在今天晚上吃什么,即餐厅? – RyanfaeScotland

+0

@RyanfaeScotland:也许,但是在SQL中没有任何赋予任意行的'ANY()'函数。否则,我会希望我的查询每次都以相同的方式运行,而不是依靠某些假定的顺序。 – gbn

+0

你的笔记在大多数实际场景中并不是真实的。 ***保持***,表格上的聚集索引将确保表格结果的一致,可预测的顺序。 – Matt

0
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
-- ============================================= 
-- Author:  Andrew Foster 
-- Create date: 28 Mar 2013 
-- Description: Allows the dynamic pull of any column value up to 255 chars from regUsers table 
-- ============================================= 
ALTER PROCEDURE dbo.PullTableColumn 
(
    @columnName varchar(255), 
    @id int 
) 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    DECLARE @columnVal TABLE (columnVal nvarchar(255)); 

    DECLARE @sql nvarchar(max); 
    SET @sql = 'SELECT ' + @columnName + ' FROM regUsers WHERE id=' + CAST(@id AS varchar(10)); 
    INSERT @columnVal EXEC sp_executesql @sql; 

    SELECT * FROM @columnVal; 
END 
GO