Pola yang cukup umum dalam aplikasi basis data yang saya gunakan adalah kebutuhan untuk membuat prosedur tersimpan untuk laporan atau utilitas yang memiliki "mode pratinjau". Ketika prosedur seperti itu melakukan pembaruan, parameter ini menunjukkan bahwa hasil tindakan harus dikembalikan, tetapi prosedur tersebut seharusnya tidak benar-benar melakukan pembaruan ke database.
Salah satu cara untuk mencapai hal ini adalah dengan hanya menulis if
pernyataan untuk parameter, dan memiliki dua blok kode lengkap; salah satunya melakukan pembaruan dan mengembalikan data dan yang lainnya hanya mengembalikan data. Tetapi ini tidak diinginkan karena duplikasi kode dan tingkat kepercayaan yang relatif rendah bahwa data pratinjau sebenarnya merupakan refleksi akurat tentang apa yang akan terjadi dengan pembaruan.
Contoh berikut mencoba untuk memanfaatkan savepoints transaksi dan variabel (yang tidak terpengaruh oleh transaksi, berbeda dengan temp tables yang) untuk menggunakan hanya satu blok kode untuk mode pratinjau sebagai mode pembaruan langsung.
Catatan: Kembalikan transaksi bukan merupakan opsi karena panggilan prosedur ini sendiri dapat bersarang dalam transaksi. Ini diuji pada 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
Saya mencari umpan balik tentang kode ini dan pola desain, dan / atau jika solusi lain untuk masalah yang sama ada dalam format yang berbeda.