Dość powszechnym wzorcem w aplikacji bazy danych, z którą pracuję, jest potrzeba utworzenia procedury składowanej dla raportu lub narzędzia, które ma „tryb podglądu”. Gdy taka procedura dokonuje aktualizacji, ten parametr wskazuje, że wyniki akcji powinny zostać zwrócone, ale procedura nie powinna faktycznie wykonywać aktualizacji bazy danych.
Jednym ze sposobów na osiągnięcie tego jest po prostu napisanie if
instrukcji dla parametru i posiadanie dwóch kompletnych bloków kodu; jeden z nich aktualizuje i zwraca dane, a drugi po prostu zwraca dane. Jest to jednak niepożądane ze względu na powielanie kodu i stosunkowo niski stopień pewności, że dane podglądu są w rzeczywistości dokładnym odzwierciedleniem tego, co stanie się z aktualizacją.
Poniższy przykład próbuje wykorzystać punkty zapisu transakcji i zmienne (na które transakcje nie mają wpływu, w przeciwieństwie do tabel tymczasowych), aby użyć tylko jednego bloku kodu dla trybu podglądu jako trybu aktualizacji na żywo.
Uwaga: Wycofywanie transakcji nie jest opcją, ponieważ to wywołanie procedury może być zagnieżdżone w transakcji. Jest to testowane na SQL Server 2012.
CREATE TABLE dbo.user_table (a int);
GO
CREATE PROCEDURE [dbo].[PREVIEW_EXAMPLE] (
@preview char(1) = 'Y'
) AS
CREATE TABLE #dataset_to_return (a int);
BEGIN TRANSACTION; -- preview mode required infrastructure
DECLARE @output_to_return TABLE (a int);
SAVE TRANSACTION savepoint;
-- do stuff here
INSERT INTO dbo.user_table (a)
OUTPUT inserted.a INTO @output_to_return (a)
VALUES (42);
-- catch preview mode
IF @preview = 'Y'
ROLLBACK TRANSACTION savepoint;
-- save output to temp table if used for return data
INSERT INTO #dataset_to_return (a)
SELECT a FROM @output_to_return;
COMMIT TRANSACTION;
SELECT a AS proc_return_data FROM #dataset_to_return;
RETURN 0;
GO
-- Examples
EXEC dbo.PREVIEW_EXAMPLE @preview = 'Y';
SELECT a AS user_table_after_preview_mode FROM user_table;
EXEC dbo.PREVIEW_EXAMPLE @preview = 'N';
SELECT a AS user_table_after_live_mode FROM user_table;
-- Cleanup
DROP TABLE dbo.user_table;
DROP PROCEDURE dbo.PREVIEW_EXAMPLE;
GO
Szukam opinii na temat tego kodu i wzorca projektowego i / lub czy istnieją inne rozwiązania tego samego problemu w różnych formatach.