sql - 如何在 SQL Server 存储过程中安排重复代码?
问题描述
我有以下存储过程:
IF EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'ChangeClientId') AND type in (N'P', N'PC'))
DROP PROCEDURE ChangeClientId
GO
CREATE PROCEDURE [dbo].[ChangeClientId]
(@dst SYSNAME,
@NewClientId INT,
@dryRun BIT = 1)
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
DECLARE @TableOfSqls TABLE (Id INT IDENTITY PRIMARY KEY, Part INT, Sql NVARCHAR(MAX))
DECLARE @Phase INT = 0
...
INSERT INTO @TableOfSqls VALUES (0, 'TRUNCATE TABLE #Failure')
INSERT INTO @TableOfSqls VALUES (0, 'GO')
SET @Phase = @Phase + 1
INSERT INTO @TableOfSqls VALUES (@Phase, '')
INSERT INTO @TableOfSqls VALUES (@Phase, 'USE [' + @dst + ']')
INSERT INTO @TableOfSqls VALUES (@Phase, 'SET XACT_ABORT ON')
INSERT INTO @TableOfSqls VALUES (0, 'IF EXISTS (SELECT 1 FROM #Failure) THROW 50000, ''Skipped due to previous errors'', 0')
INSERT INTO @TableOfSqls VALUES (0, 'INSERT INTO #Failure VALUES (0)')
...
END
这个代码块
INSERT INTO @TableOfSqls VALUES (0, 'TRUNCATE TABLE #Failure')
INSERT INTO @TableOfSqls VALUES (0, 'GO')
SET @Phase = @Phase + 1
INSERT INTO @TableOfSqls VALUES (@Phase, '')
INSERT INTO @TableOfSqls VALUES (@Phase, 'USE [' + @dst + ']')
INSERT INTO @TableOfSqls VALUES (@Phase, 'SET XACT_ABORT ON')
INSERT INTO @TableOfSqls VALUES (0, 'IF EXISTS (SELECT 1 FROM #Failure) THROW 50000, ''Skipped due to previous errors'', 0')
INSERT INTO @TableOfSqls VALUES (0, 'INSERT INTO #Failure VALUES (0)')
在存储过程中重复多次。在 C# 中,我会将它放在嵌套函数中。在 T-SQL 中,我应该能够创建一个临时存储过程或类似的东西,但我不确定。
所以,我的问题是 - 安排这个重复代码以减少混乱的最佳方法是什么?
基本原理
这个存储过程生成一个大的动态 SQL 并执行它。但是,它支持空运行,即显示 SQL 但不运行。因此,该过程将所有 SQL 语句累积到一个表中,然后将其输出或组成一个 SQL 字符串并执行它。但是,有一个问题,它是分阶段进行的。每个阶段都用所描述的重复但不完全相同的代码段分隔,因为@Phase
在中间递增。
解决方案
我通过在我的内部添加一个临时存储过程并调用它而不是重复块来解决它。
这是代码:
...
DECLARE @Phase INT = 0
SET @Sql = '
CREATE PROCEDURE #ChangeClientIdSqlHelper(@Phase INT)
AS
BEGIN
DECLARE @TableOfSqls TABLE (Id INT IDENTITY PRIMARY KEY, Part INT, Sql NVARCHAR(MAX))
INSERT INTO @TableOfSqls VALUES (0, '''')
INSERT INTO @TableOfSqls VALUES (0, ''TRUNCATE TABLE #Failure'')
INSERT INTO @TableOfSqls VALUES (0, ''GO'')
INSERT INTO @TableOfSqls VALUES (@Phase, '''')
INSERT INTO @TableOfSqls VALUES (@Phase, ''USE ' + QUOTENAME(@dst) + ''')
INSERT INTO @TableOfSqls VALUES (@Phase, ''SET XACT_ABORT ON'')
INSERT INTO @TableOfSqls VALUES (0, ''IF EXISTS (SELECT 1 FROM #Failure) THROW 50000, ''''Skipped due to previous errors'''', 0'')
INSERT INTO @TableOfSqls VALUES (0, ''INSERT INTO #Failure VALUES (0)'')
INSERT INTO @TableOfSqls VALUES (0, '''')
SELECT Part, Sql FROM @TableOfSqls ORDER BY Id
END
'
EXEC(@Sql)
...
SET @Phase = @Phase + 1
INSERT INTO @TableOfSqls EXEC #ChangeClientIdSqlHelper @Phase
...
SET @Phase = @Phase + 1
INSERT INTO @TableOfSqls EXEC #ChangeClientIdSqlHelper @Phase
...
推荐阅读
- xml - s4s-elt-invalid-content.1:“#X”的内容无效。元素“元素”无效、放错位置或出现过于频繁
- quarkus - 如何获取当前的 HttpRequest quarkus?
- sql - SQL - 在同一查询上下文中引用列值
- mysql - Laravel 多对多合并 Pivot?
- amazon-web-services - 有没有使用相同 terraform 脚本的跨账户部署的好例子?
- python - 加载页面时出现 Selenium ChromeDriver 错误
- android - 每当我触摸并按住屏幕上的几乎任何元素时,都会出现灰色框,其中包含视图标签。我怎样才能删除这个?
- c++ - 二叉树和处理器(C++ Codeforces 问题)
- python - 使用列表值来确定哪个是父级,哪个是子级
- video - mp4 视频使用 mplayer 在命令行中显示,但不在脚本中