SQL Server 2008存储过程不返回动态查询

时间:2016-06-16 10:06:47

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

以下存储过程动态确定指定表中的列并返回所有非空的列,但是存储的proc返回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

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

4 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

将程序更改为此程序,然后重试:

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的值分配给变量。此外,有时此输出值可以是NULL,但STRING + NULL等于NULL。我添加了一个缓冲变量@TempParamOut来存储中间结果。您正在使用@ParamOut变量并在每次执行动态T-SQL语句时覆盖其值。这就是为什么根本没有进行连接的原因。

答案 2 :(得分:1)

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

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

keyboard

请注意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 + ']',因此按名称过滤可能不是一个安全的解决方案。

答案 3 :(得分:1)

关闭@gotqn的回答。

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

改为将其改为IF EXISTS,其中NOT NULL和Len&gt; 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