以下存储过程动态确定指定表中的列并返回所有非空的列,但是存储的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
答案 0 :(得分:2)
当存在基于NULL的附加(使用加号(+)符号)时,我们通常会将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