在我使用的数据库应用程序中,一个相当普遍的模式是需要为具有“预览模式”的报表或实用程序创建存储过程。当此类过程确实更新时,此参数指示应返回操作结果,但该过程实际上不应执行对数据库的更新。
一种实现方法是简单地if
为参数编写一条语句,并具有两个完整的代码块。其中一个确实更新并返回数据,而另一个仅返回数据。但这是不希望的,因为代码重复并且相对较低的可信度,即预览数据实际上是对更新所发生情况的准确反映。
下面的示例尝试利用事务保存点和变量(与临时表相反,不受事务影响)与临时表相比,仅将单个代码块用作实时更新模式。
注意:不能选择事务回滚,因为此过程调用本身可能嵌套在事务中。这已在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
我正在寻找有关此代码和设计模式的反馈,并且/或者是否希望以不同的格式存在针对同一问题的其他解决方案。