动态SQL的输出变量

时间:2013-05-22 14:18:03

标签: sql-server-2008 tsql stored-procedures

我有一个问题,我尝试从存储过程内的动态T-SQL查询输出值。

我尝试执行以下操作,如果发现了某些内容,只需输出1:

SET NOCOUNT ON
DECLARE @returnValue int
DECLARE @Statement nvarchar(400)
set @Statement = 'SELECT @result=''1'' FROM INFORMATION_SCHEMA.COLUMNS
                  WHERE TABLE_NAME = ''sourceTable''
                  AND COLUMN_NAME = @columnIN
                  AND TABLE_SCHEMA = ''dbo'''
exec sp_executesql @Statement, 
    N'@columnIN nvarchar(60),@result INT OUTPUT', 
    @columnIN = @column, @result=@returnValue OUTPUT    
select @returnValue      

目前这会产生NULL。有没有人知道我错过了什么?

其他信息: 我尝试查找的列例如是column1。如果我用...AND CLOUMN_NAME = 'column1' ...运行SQL查询,我得到1回。 如果我在SP中打印@column变量,我会得到'column1'。 @column在SP中声明为nvarchar(60)的输入变量:PROCEDURE [dbo].[usp_checkColumn] (@column nvarchar(60), @result INT OUTPUT)

根据要求,完整的SP在这里:

  Create PROCEDURE [dbo].[usp_checkColumn] (@column nvarchar(60), @result INT OUTPUT)
AS
BEGIN

    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON
    DECLARE @returnValue int
    DECLARE @Statement nvarchar(400)
    set @Statement = 'SELECT @result=''1'' FROM INFORMATION_SCHEMA.COLUMNS
                       WHERE TABLE_NAME = ''t_table''
                       AND COLUMN_NAME = @columnIN
                        AND TABLE_SCHEMA = ''dbo'''

    exec sp_executesql @Statement, N'@columnIN nvarchar(60),@result INT OUTPUT', @columnIN = @column, @result=@returnValue OUTPUT    
    select @returnValue      
    return @returnValue

END

以下是我打电话给SP的方式:

DECLARE fcursor CURSOR
FOR
  select FieldName 
  from t_fieldDefinition 
OPEN fcursor

Fetch next from fcursor into @field;  
WHILE @@FETCH_STATUS = 0
BEGIN
  SET @tmpField = '''' + @field + ''''
  SET @field ='[' + @field  + ']' 
  set @available = 0 
  exec usp_checkColumn @tmpField,@available OUTPUT

如果我在usp_checkColumn中打印[@column]变量,我会在''中找到正确的列。如果我复制&粘贴此变量的打印并将其插入查询中我得到1回,如果我运行SP我得到NULL(转换为0,因为NULL对INT变量无效)返回。

以下是t_fieldDefinition表的内容:

FieldName   ID
Source      5
column1     6
column2     7
Client      8
asd BSX     9
bsd         10
esd         11
esx         12

这是t_table表的定义:

ID          bigint          Unchecked
Source      varchar(250)    Checked
column1     varchar(250)    Checked
column2     nvarchar(100)   Checked
Client      varchar(10)     Checked
asd         varchar(250)    Checked
[asd BSX]   varchar(250)    Checked

这意味着它应该为表定义中的所有内容返回1,为所有其他内容返回0。具有空白区域的字段是否可能成为问题?虽然手动操作时它们也能正常工作。这并不是说我真的可以选择改变它,但至少我现在可以解决这个问题。

1 个答案:

答案 0 :(得分:0)

我要冒昧地回答这个问题。

我不建议使用游标遍历每一列,只是为了测试列是否存在于另一个表中。如果您坚持使用游标,则可以使用子查询将您循环的结果限制为仅限于另一个表中不存在的列,从而无需单独检查每个列的存储过程(顺便说一句,我认为作为用户功能更有意义):

DECLARE fcursor CURSOR
FOR
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
where table_name = 't_table' and not column_name in 
(   
    SELECT COLUMN_Name FROM INFORMATION_SCHEMA.COLUMNS
    where table_name = 't_fieldDefinition'
) 

如果你的目标确实是改变表以添加任何缺失的列,那么可以通过消除游标并使用FOR XML输出结果来改进这一点:

declare @sql varchar(max)
set @sql = 
(
    SELECT cast('ALTER TABLE t_fieldDefinition ADD [' + COLUMN_NAME + '] INT;' as varchar(max)) FROM INFORMATION_SCHEMA.COLUMNS
    where table_name = 't_table' and not column_name in 
    (   
        SELECT COLUMN_Name FROM INFORMATION_SCHEMA.COLUMNS
        where table_name = 't_fieldDefinition'
    ) FOR XML PATH ('')
)
print @sql
exec (@sql)