我创建了一个存储过程,它接受动态列列表(基于所选参数),然后将它们连接起来。然后将其保存到全局临时表,然后传递到动态SQL语句,该语句将根据参数传递列名。当我运行另一个执行此存储过程的脚本时,它抱怨说:
无法确定元数据,因为语句'EXEC(@SqlCommand)' 在过程'CL_GetDynamicColumns2'中包含动态SQL。请考虑使用WITH RESULT SETS子句显式描述结果集。
这里的问题是我不能使用WITH RESULT SETS,因为列的输出是动态的,我永远不知道将返回多少列。列名始终以不同方式输出(如果参数已更改)。
是否可以创建一个可能动态获取我想要的列而不是使用动态SQL的函数?
--Script 1: Everything is first generated in this stored proc
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CL_GetDynamicColumns2]
(
@TableName NVARCHAR(MAX),
@Currency NVARCHAR(MAX),
@Type NVARCHAR(MAX),
@ParameterValue NVARCHAR(MAX),
@WhereField NVARCHAR(MAX),
@ColumnList NVARCHAR(MAX) = NULL,
@SqlCommand NVARCHAR(MAX) = NULL
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @MyTableVar TABLE
(
[TABLE_CATALOG] nvarchar(128),
[TABLE_SCHEMA] nvarchar(128),
[TABLE_NAME] nvarchar(128),
[COLUMN_NAME] nvarchar(128),
[ORDINAL_POSITION] INT,
[COLUMN_DEFAULT] NVARCHAR(4000),
[IS_NULLABLE] VARCHAR(3),
[DATA_TYPE] nvarchar(128),
[CHARACTER_MAXIMUM_LENGTH] INT,
[CHARACTER_OCTET_LENGTH] INT,
[NUMERIC_PRECISION] TINYINT,
[NUMERIC_PRECISION_RADIX] SMALLINT,
[NUMERIC_SCALE] INT,
[DATETIME_PRECISION] SMALLINT,
[CHARACTER_SET_CATALOG] nvarchar(128),
[CHARACTER_SET_SCHEMA] nvarchar(128),
[CHARACTER_SET_NAME] nvarchar(128),
[COLLATION_CATALOG] nvarchar(128),
[COLLATION_SCHEMA] nvarchar(128),
[COLLATION_NAME] nvarchar(128),
[DOMAIN_CATALOG] nvarchar(128),
[DOMAIN_SCHEMA] nvarchar(128),
[DOMAIN_NAME] nvarchar(128)
)
INSERT INTO @MyTableVar
SELECT *
FROM information_schema.columns AS C
WHERE C.TABLE_NAME = @TableName
AND C.DATA_TYPE NOT IN ('decimal','numeric')
UNION ALL
SELECT *
FROM information_schema.columns AS C
WHERE C.TABLE_NAME = @TableName
AND C.DATA_TYPE IN ('decimal','numeric')
AND C.COLUMN_NAME LIKE '%' + @Currency + '%'
AND C.COLUMN_NAME LIKE '%' + @Type + '%'
DECLARE @MyTableVar2 TABLE
(
[TABLE_CATALOG] nvarchar(128),
[TABLE_SCHEMA] nvarchar(128),
[TABLE_NAME] nvarchar(128),
[TABLE_COLUMNS] nvarchar(MAX)
)
INSERT INTO @MyTableVar2 ([TABLE_CATALOG], [TABLE_SCHEMA], [TABLE_NAME],
[TABLE_COLUMNS])
SELECT DISTINCT T.TABLE_CATALOG, T.TABLE_SCHEMA, T.TABLE_NAME,
STUFF(
(SELECT ', ' + QUOTENAME(COLUMN_NAME)
FROM @MyTableVar AS TC
WHERE TC.TABLE_NAME = T.TABLE_NAME
FOR XML PATH (''))
, 1, 1, '') AS TABLE_COLUMNS
FROM @MyTableVar AS T
/*Final step: Build Dynamic Query*/
SET @ColumnList = (SELECT L.TABLE_COLUMNS FROM @MyTableVar2 AS L)
SET @SqlCommand = 'SELECT ' + @ColumnList +
' Into ##TempCatch ' +
' FROM ' + @TableName +
' WHERE ' + @WhereField + ' IN ' + '(SELECT * FROM ' +
'dbo.fnToDelimitedTable( ' + @ParameterValue + ' ,'',''))'
EXEC (@SqlCommand)
SELECT * FROM ##TempCatch
DROP TABLE ##TempCatch
END
--script 2 to gather results from first stored procedure
DECLARE @TableName NVARCHAR(MAX) = 'SM_COLLECTIONS_WTK_RANK'
DECLARE @Currency NVARCHAR(MAX) = 'GBP'
DECLARE @Type NVARCHAR(MAX) = 'Billed'
DECLARE @ParameterValue NVARCHAR(MAX) = '1503515'
DECLARE @WhereField NVARCHAR(MAX) = 'FK_MATTER'
DECLARE @ColumnList NVARCHAR(MAX)
DECLARE @SqlCommand NVARCHAR(MAX)
DECLARE @SPWithParams NVARCHAR(MAX)
SELECT TOP 0 *
INTO ##holdingtable
FROM
OPENROWSET('SQLNCLI','Server=;UID=;PWD=','SET FMTONLY OFF EXEC
dbo.CL_GetDynamicColumns2')
--set the parameters of the procedure
SET @SPWithParams = 'EXEC dbo.CL_GetDynamicColumns2' + @TableName +
@Currency + @Type + @ParameterValue + @WhereField + @ColumnList +
@SqlCommand
--execute the procedure
EXEC ProcToTable 'holdingtable', @SPWithParams
--view the results
SELECT * FROM ##holdingtable
DROP TABLE ##holdingtable