我一直在实现一个用于生成动态列视图的存储过程。 此视图应表示以下PIVOT SQL-Statement:
为什么我使用带有动态SQL的存储过程? 要实现一个数据库对象,其行为类似于在MSSQL 2005上使用的显示语句,直到现在,以及从9i开始的Oracle(不幸的是......)。 现在,由于缺少关于如何以更好的方式实现的更深入的知识,我决定使用存储过程。
但是现在我陷入困境,任何建议都受到高度赞赏。此外,欢迎任何关于如何以更好的方式实现但具有相同结果的建议,如所示的SQL Fiddle Demo。
我的SP目前看起来像这样:
create procedure GeneratePivotLeistungsbewertungen
as
SET NOCOUNT ON;
DECLARE cActivityNames CURSOR FOR
SELECT distinct ActivityName
FROM Leistungsbewertungen
DECLARE @name VARCHAR(32)
DECLARE @dyn_col_list NVARCHAR(MAX)
OPEN cActivityNames
FETCH NEXT FROM cActivityNames INTO @name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @dyn_col_list = @dyn_col_list + N'(select lb.Bewertungswert from Leistungsbewertungen lb where lb.ActivityName = '+ @name +' and lb.LeistungsId = o.LeistungsId)' + @name + ','
FETCH NEXT FROM cActivityNames INTO @name
END
deallocate cActivityNames
select LEFT(@dyn_col_list, LEN(@dyn_col_list)-1)
DECLARE @execVar NVARCHAR(MAX) = N' VIEW dbo.PivotLeistungsbewertungen
AS
SELECT max(o.LeistungsId) LeistungsId, max(o.Gnr) GOP,' + @dyn_col_list +
'FROM leistungen o group by o.LeistungsId'
SET @execVar = CASE WHEN EXISTS
(SELECT 1 FROM sys.views WHERE [object_id] = OBJECT_ID('dbo.PivotLeistungsbewertungen'))
THEN N'ALTER' ELSE N'CREATE' + @execVar END;
BEGIN TRY
EXEC sp_executesql @execVar;
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
END CATCH
go
任何想法,如果你这样称呼它不会创建视图:
USE [Q20133_0_NO]
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[GeneratePivotLeistungsbewertungen]
SELECT 'Return Value' = @return_value
GO
EDITED for Solutions(2005 / 2008R2)
更新了工作存储过程(在SQLServer 2008 R2下测试
CREATE PROCEDURE GeneratePivotLeistungsbewertungen
AS
SET NOCOUNT ON;
DECLARE @name VARCHAR(32)
DECLARE @dyn_col_list NVARCHAR(MAX) = ''
SELECT @dyn_col_list = isnull(@dyn_col_list + ',', '') + N'(
select lb.Bewertungswert
from Leistungsbewertungen lb
where
lb.ActivityName = ''' + ActivityName + ''' and
lb.LeistungsId = o.LeistungsId
)' + ActivityName
FROM Leistungsbewertungen
GROUP BY ActivityName
DECLARE @execVar NVARCHAR(MAX) = N' VIEW dbo.PivotLeistungsbewertungen
AS
SELECT max(o.LeistungsId) LeistungsId, max(o.Gnr) GOP' + @dyn_col_list + ' FROM leistungen o group by o.LeistungsId'
SET @execVar = CASE
WHEN EXISTS (
SELECT 1
FROM sys.VIEWS
WHERE [object_id] = OBJECT_ID('dbo.PivotLeistungsbewertungen')
)
THEN N'ALTER' + @execVar
ELSE N'CREATE' + @execVar
END;
BEGIN TRY
EXEC sp_executesql @execVar;
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
END CATCH
对于SQLServer 2005,它必须遵循实施(也适用于2008 R2)
DECLARE @execVar NVARCHAR(200)
SET @execVar = CASE
WHEN EXISTS (
SELECT 1
FROM sys.procedures
WHERE [object_id] = OBJECT_ID('dbo.GeneratePivotLeistungsbewertungen')
)
THEN N'DROP PROCEDURE GeneratePivotLeistungsbewertungen;'
END;
EXEC(@execVar)
go
CREATE PROCEDURE GeneratePivotLeistungsbewertungen
AS
SET NOCOUNT ON;
DECLARE @name VARCHAR(32)
DECLARE @dyn_col_list NVARCHAR(MAX)
SET @dyn_col_list = ''
SELECT @dyn_col_list = isnull(@dyn_col_list + ',', '') + N'(
select lb.Bewertungswert
from Leistungsbewertungen lb
where
lb.ActivityName = ''' + ActivityName + ''' and
lb.LeistungsId = o.LeistungsId
) AS ' + ActivityName
FROM Leistungsbewertungen
GROUP BY ActivityName
ORDER BY MAX(Bewertungsschritt)
DECLARE @execVar NVARCHAR(MAX)
SET @execVar = N' VIEW dbo.PivotLeistungsbewertungenView
AS
SELECT max(o.LeistungsId) LeistungsId, max(o.Gnr) GOP' + @dyn_col_list + ' FROM leistungen o group by o.LeistungsId'
SET @execVar = CASE
WHEN EXISTS (
SELECT 1
FROM sys.VIEWS
WHERE [object_id] = OBJECT_ID('dbo.PivotLeistungsbewertungenView')
)
THEN N'ALTER' + @execVar
ELSE N'CREATE' + @execVar
END;
BEGIN TRY
EXEC sp_executesql @execVar;
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
END CATCH
GO
答案 0 :(得分:1)
我几乎可以肯定你只需要初始化你的@dyn_col_list
就可以了:
set @dyn_col_list = ''
打开光标前。无论如何,如果你有这样的问题,快速检查它的最好方法是在执行前print @execVar
,以确定你正在执行的是什么。
另外,我通常使用这种语法而不是游标:
select
@dyn_col_list = isnull(@dyn_col_list + ',', '') +
N'(
select lb.Bewertungswert
from Leistungsbewertungen lb
where
lb.ActivityName = '+ ActivityName +' and
lb.LeistungsId = o.LeistungsId
)' + ActivityName
from Leistungsbewertungen
group by ActivityName
它更短,自动删除最后一个逗号,你不需要初始化@dyn_col_list
(实际上,如果有可能它不为null,你必须不初始化它或用null初始化它)