SQL Server 2008 存储过程未从动态查询返回输出

SQL Server 2008 Stored Proc not returning output from dynamic query

以下存储过程动态确定指定的 table 和 return 中所有不为空的列,但是存储过程 returning null 尽管有结果回到自己测试动态查询时,我是否正确处理了动态查询 return 结果?

CREATE PROCEDURE [dbo].[spGetTables] 
(
    @TableName    varchar(255)
,@ParamOut    varchar(2000) OUTPUT
)
AS

declare @CommaString varchar(max)
set @CommaString = ''

Declare @col varchar(255), @cmd nvarchar(max)
declare @colName varchar(2000)
SET @colName = ''

DECLARE getinfo cursor for
SELECT c.name FROM sys.tables t JOIN sys.columns c ON t.Object_ID = c.Object_ID
WHERE t.Name = @TableName 

OPEN getinfo

FETCH NEXT FROM getinfo into @col

WHILE @@FETCH_STATUS = 0
BEGIN

    SELECT @cmd = 'IF NOT EXISTS (SELECT top 1 * FROM [' + @TableName + '] WHERE [' + @col + '] IS NULL or len([' + @col + ']) < 1) BEGIN select ''' + @col + ',''  END'

    exec sp_executesql @cmd, N'@Result varchar(max) out', @ParamOut out

    set @ParamOut = @ParamOut + @CommaString

    FETCH NEXT FROM getinfo into @col
END

PRINT 'Result: '+@ParamOut

CLOSE getinfo
DEALLOCATE getinfo
RETURN 0

当存在基于 NULL 的追加(使用加号 (+))时,我们通常会得到 NULL 作为输出。为了克服,请按照以下步骤操作,

  1. 打印动态创建的 SQL 语句并查看导致问题的字段
  2. 尝试用空字符串 ('') 替换基于 NULL 的值

把程序改成这个再试一次:

CREATE PROCEDURE [dbo].[spGetTables] 
(
    @TableName    varchar(255)
,@ParamOut    varchar(2000) OUTPUT
)
AS

declare @CommaString varchar(max)
set @CommaString = ''

Declare @col varchar(255), @cmd nvarchar(max)
declare @colName varchar(2000)
SET @colName = ''

DECLARE getinfo cursor for
SELECT c.name FROM sys.tables t JOIN sys.columns c ON t.Object_ID = c.Object_ID
WHERE t.Name = @TableName 

OPEN getinfo

FETCH NEXT FROM getinfo into @col

DECLARE @TempParamOut varchar(2000) = '';

WHILE @@FETCH_STATUS = 0
BEGIN

    SELECT @cmd = ' IF NOT EXISTS (SELECT top 1 * FROM [' + @TableName + '] WHERE [' + @col + '] IS NULL or len([' + @col + ']) < 1) BEGIN select @Result= ''' + @col + ',''  END'

    exec sp_executesql @cmd, N'@Result varchar(max) out', @TempParamOut out

    set @ParamOut = ISNULL(@ParamOut,'') + ISNULL(@TempParamOut,'') + @CommaString;
    set @TempParamOut = '';
    FETCH NEXT FROM getinfo into @col
END


CLOSE getinfo
DEALLOCATE getinfo
RETURN 0

在动态 T-SQL 语句中,您需要将 SELECT 的值赋给变量。此外,有时此输出值可以是 NULLSTRING + NULL 等于 NULL。我添加了一个缓冲区变量 @TempParamOut 用于存储中间结果。您正在使用 @ParamOut 变量并在每次执行动态 T-SQL 语句时覆盖它的值。这就是为什么根本不执行连接的原因。

@gotqn 已经发现了你的错误——你没有为你的输出变量分配任何东西。

但这是另一种没有光标和单一来源的方法 table 扫描:

DECLARE
    @sql VARCHAR(MAX),
    @TableName VARCHAR(100) = 'dbo.MyTable'


SELECT @sql = 'SELECT STUFF(''''' +
    (
        SELECT 
            '
            +ISNULL(
                    MIN(CASE WHEN t.' + QUOTENAME (c.name) + ' IS NOT NULL AND LEN(t.' + QUOTENAME (c.name) + ') >= 1 THEN '', ' + QUOTENAME (c.name) + ''' ELSE '''' END)
                    , '''')'
        FROM sys.columns c
        WHERE c.[object_id] = t.[object_id]
        ORDER BY c.column_id
        FOR XML PATH(''), TYPE 
     ).value('.', 'VARCHAR(MAX)') + ', 1, 1, '''') FROM ' 
     + QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + '.' + QUOTENAME(t.name) + ' as t'
FROM sys.tables t
WHERE t.object_id = object_id(@TableName, 'U')

print @sql

EXEC (@sql)

EXEC ('select top 10 * from ' + @TableName)

请注意此处的 QUOTENAME 函数 - 最好用它代替 '[' + name + ']'。当然,对象可能有不同的 schema,因此按名称过滤可能不是一个安全的解决方案。

离开@gotqn 的回答。

当我 运行 它时,它没有正确排序结果并且返回的行太少。其中一些是因为字段中的垃圾值,例如。 “ ”并且检查有点不对劲。

改为 IF EXISTS,其中 NOT NULL 且 Len > 0

ALTER PROCEDURE [dbo].[spGetTables] 
(
    @TableName    varchar(255)
,@ParamOut    varchar(2000) OUTPUT
)
AS

declare @CommaString varchar(max)
set @CommaString = ''

Declare @col varchar(255), @cmd nvarchar(max)
declare @colName varchar(2000)
SET @colName = ''

DECLARE getinfo cursor for
SELECT c.name FROM sys.tables t JOIN sys.columns c ON t.Object_ID = c.Object_ID
WHERE t.Name = @TableName 

OPEN getinfo

FETCH NEXT FROM getinfo into @col

DECLARE @TempParamOut varchar(2000) = '';

WHILE @@FETCH_STATUS = 0
BEGIN

    SELECT @cmd = 'IF EXISTS (SELECT top 1 * FROM [' + @TableName + '] WHERE [' + @col + '] IS NOT NULL and len(LTRIM(RTRIM(REPLACE(REPLACE(REPLACE([' + @col + '], CHAR(10), ''''), CHAR(13), ''''), CHAR(9), '''')))) > 0) BEGIN select  @Result=''' + @col + ','' END'

    exec sp_executesql @cmd, N'@Result varchar(max) out', @TempParamOut out

    set @ParamOut = ISNULL(@ParamOut,'') + ISNULL(@TempParamOut,'') + @CommaString;
    set @TempParamOut = '';

    FETCH NEXT FROM getinfo into @col
END

CLOSE getinfo
DEALLOCATE getinfo
RETURN 0