動的な列を持つビューを生成するためのストアド プロシージャの実装に行き詰まっています。このビューは、次に示すように、次の PIVOT SQL ステートメントを表す必要があります。
なぜ動的 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
ソリューション用に編集 (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