t-sql执行结果

介绍 (Introduction)

Context

语境

Back in my days at school, I followed a course entitled “Object-Oriented Software Engineering” where I learned some “design patterns” like Singleton and Factory. If you are not familiar with this expression, here is a definition of a design pattern from Wikipedia:

回到学校时,我参加了一个名为“面向对象软件工程”的课程,在那里我学习了一些“设计模式”,例如Singleton和Factory。 如果您不熟悉此表达式,请参见Wikipedia中的设计模式定义:

“In software engineering, a software design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. It is not a finished design that can be transformed directly into source or machine code. It is a description or template for how to solve a problem that can be used in many different situations. Design patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system.”

“在软件工程中 , 软件设计模式是针对软件设计中给定上下文中常见问题的通用可重用解决方案。 它不是可以直接转换为源代码或机器代码的最终设计。 它是关于如何解决可以在许多不同情况下使用的问题的描述或模板。 设计模式是形式化的最佳实践 ,程序员可以在设计应用程序或系统时用来解决常见问题。”

Well, as stated above, these design patterns are not a finished design, in and of itself, and must be written in the programming language of our choice. Transact SQL is also a programming language and we could also imagine the implementation of those design patterns for data generation. Actually, the subject of this article can be seen as a specialized version of the Command design pattern.

嗯,如上所述,这些设计模式本身并不是完成的设计,必须使用我们选择的编程语言编写。 Transact SQL也是一种编程语言,我们还可以想象这些设计模式的实现以生成数据。 实际上,本文的主题可以看作是Command设计模式的专门版本。

The particular design pattern this article is about can be used in multiple situations and we will review it in details in a few seconds.

本文涉及的特定设计模式可以在多种情况下使用,我们将在几秒钟内对其进行详细审查。

In following sections, we will focus on the problem that we want to solve and on the general solution to that problem. This solution constitutes therefore a design pattern for the solution. Once we know this design pattern, we can specialize it to fulfill the needs of a particular situation and that’s what we’ll do in last section.

在以下各节中,我们将集中于我们要解决的问题和该问题的一般解决方案。 因此,该解决方案构成了该解决方案的设计模式。 一旦知道了这种设计模式,就可以对其进行专门化以满足特定情况的需求,这就是我们在上一节中要做的。

设计模式定义 (Design pattern definition)

The problem

问题

Now, it’s time to talk a little bit about the problem we want to solve in this article. I’ve been confronted to it more than once and I’m pretty sure that you’re are not stranger to it neither.

现在,该讨论我们要在本文中解决的问题了。 我已经不止一次面对它,而且我很确定你对它也不陌生。

Let’s say we want to develop an application running T-SQL commands that will insert new records into a set of tables. This application can be a script generator, a monitoring or reporting tool or anything else you could imagine. We would like to be able to get back all data related to a particular execution of this application. Why would we do that? There can be multiple answers:

假设我们要开发一个运行T-SQL命令的应用程序,该命令会将新记录插入到一​​组表中。 该应用程序可以是脚本生成器,监视或报告工具或您可以想象的任何其他工具。 我们希望能够检索与该应用程序的特定执行相关的所有数据。 我们为什么要这样做? 可能有多个答案:

  • To limit computation costs and just keep results of a treatment for further review 为了限制计算成本,仅保留处理结果以供进一步检查
  • To take these data as input of another process which would transform it to something else, in short to log steps in a data transformation process. 要将这些数据作为另一个过程的输入,该过程会将其转换为其他内容,简而言之,是记录数据转换过程中的步骤。
  • Or anything else you might think of 或其他您可能想到的

With this approach, we can divide complex code into smaller pieces in which the business logic is less complex and easier to manage. As we divide these pieces of code, we could also run the processing asynchronously.

使用这种方法,我们可以将复杂的代码分成较小的部分,其中业务逻辑不太复杂且更易于管理。 在划分这些代码段时,我们还可以异步运行处理。

The following shows an example process in which we could eventually use the solution defined in this article. Green arrows mean that source process has to succeed for destination process to run. The arrow itself means that data generated from source process is used as input (or loaded) by destination process.

下面显示了一个示例过程,在该过程中我们最终可以使用本文定义的解决方案。 绿色箭头表示源进程必须成功才能运行目标进程。 箭头本身意味着从源进程生成的数据被目标进程用作输入(或加载)。

Our application can be written in another language but the solution to the problem has to be written in T-SQL because the application can be composed of multiple executables and we don’t want to write custom libraries to include in each individual executable.

我们的应用程序可以用另一种语言编写,但是问题的解决方案必须用T-SQL编写,因为该应用程序可以由多个可执行文件组成,并且我们不想编写包含在每个单独的可执行文件中的自定义库。

The solution

解决方案

Now, let’s discuss some points that will lead us towards the entire solution for purpose better understanding. We will segment this solution into two distinct parts: the “what” and the “how”. The “what” consists in the objects we need while the “how” is the way we will use these objects. Using both together constitutes the actual solution to the presented problem.

现在,让我们讨论一些要点,这些要点将引导我们走向整个解决方案,以更好地理解目的。 我们将解决方案分为两个不同的部分:“什么”和“如何”。 “什么”包含我们需要的对象,而“如何”则是我们使用这些对象的方式。 两者一起使用构成了所提出问题的实际解决方案。

What do we need?

我们需要什么?

The biggest need that we can understand from problem explanation is that we need to uniquely identify an execution of the application. So, we need to assign a unique identifier during execution. In terms of implementation. This unique identifier can be either:

从问题解释中我们可以理解的最大需求是,我们需要唯一地标识应用程序的执行。 因此,我们需要在执行期间分配一个唯一的标识符。 在执行方面。 此唯一标识符可以是:

  • Sequence object and Sequence对象和NEXT VALUE FOR statement NEXT VALUE FOR语句生成的值
  • IDENTITY function or data type IDENTITY函数或数据类型生成的值
  • A value generated using NEWID() function.
  • 使用NEWID()函数生成的值。
  • A value based on datetime or timestamp of execution (be aware of the limitations of DATETIME data type and prefer DATETIME2 if milliseconds matter)
  • 基于日期 时间或执行时间戳的值(请注意DATETIME数据类型的限制,如果毫秒为单位,则首选DATETIME2
  • A random but not already used value following a design pattern 遵循设计模式的随机但尚未使用的值

As we need to be able to refer to an execution of the application and get back the results of that execution, this unique identifier must be stored in a table. We’ll refer to that table as the “execution log”.

由于我们需要能够引用应用程序的执行并获取该执行的结果,因此该唯一标识符必须存储在表中。 我们将该表称为“执行日志”。

But we can’t only log unique identifiers into that table because we might need to read other information to know which one we should use for further processing. You will find below a list of information I tend to keep in order to get back to a particular execution of an applications. This list is not static and you can either remove or add one or more items to it.

但是,我们不能仅将唯一标识符记录到该表中,因为我们可能需要读取其他信息才能知道应该使用哪个标识符进行进一步处理。 您将在下面找到我倾向于保留的信息列表,以便返回到特定的应用程序执行情况。 此列表不是静态的,您可以删除或添加一个或多个项目。

  • A name for the treatment performed by the application 应用程序执行的处理的名称
    • The name of the login (can be extended with the name of his database user both can be different in your environment) 登录名(可以用他的数据库用户名扩展,在您的环境中两者都可以不同)
    • The IP Address IP地址
    • The name of the computer 电脑名称
    • The name of the executable 可执行文件的名称
  • The Time when the execution began 开始执行的时间
  • The Time when the execution completed 执行完成的时间
  • The List of values used for parameters of that execution 用于执行参数的值列表
  • The outcome of the execution (“SUCCESS” or “ERROR” or NULL)
  • 执行的结果(“ SUCCESS ”或“ ERROR ”或NULL
  • The error message that lead to a non-successful outcome 导致不成功结果的错误消息

You can look at following T-SQL statement that corresponds to the creation statement for the ExecutionLog table using previous list.

您可以使用上一个列表查看对应于ExecutionLog表的创建语句的以下T-SQL语句。


CREATE TABLE [ExecutionLog] ([ExecutionId]           <DATATYPE_TO_BE_DEFINED> NOT NULL,[ExecutionName]         VARCHAR(512)  NOT NULL,[SQLLogin]              VARCHAR(512)  NOT NULL,[ClientNetAddress]      VARCHAR(128)  NOT NULL,[ClientHostName]        VARCHAR(128)  NOT NULL,[ClientProgramName]     VARCHAR(256)  NOT NULL,[StartTime]             DATETIME2     NOT NULL,[EndTime]               DATETIME2     NULL,[ExecutionParams]       VARCHAR(MAX)  NULL,[Outcome]               VARCHAR(64)   NULL,[ErrorDetails]          VARCHAR(MAX)  NULL
)

With this information, we really can present, to a user, a subset of the entire execution log with only its own actions. We can also stop a cascading process by checking the execution success information: if the execution was not successful and we needed the results of this execution to perform an additional treatment on this, then it’s of no use to carry on…

有了这些信息,我们实际上可以仅通过自己的操作向用户呈现整个执行日志的子集。 我们还可以通过检查执行成功信息来停止级联过程:如果执行不成功,并且我们需要执行结果来对此进行其他处理,那么继续进行就没有用了……

How will we do it?

我们将如何做?

At this point, we’ve answered the “what” question: we exactly know what we need to address the challenge defined in this article. Now, let’s talk about the “how”: how will we make it happen?

在这一点上,我们已经回答了“什么”问题:我们完全知道我们需要解决本文定义的挑战。 现在,让我们谈谈“如何”:我们将如何实现它?

We could write a set of T-SQL queries inside the application that will use the execution log, but this means that if we want to change a piece of code in these queries, we need to change it in every executable that works with this design pattern. There is, to me, a better solution to that problem.

我们可以在应用程序内编写一组使用执行日志的T-SQL查询,但这意味着,如果我们想在这些查询中更改一段代码,则需要在与此设计兼容的每个可执行文件中进行更改。模式。 对我来说,有一个更好的解决方案。

Instead, we should create a stored procedure that will generate the unique identifier and store the information discussed above. We will call this stored procedure “LogNewExecution“. Here is the interface for such a function. Again, this can be customized to your needs.

相反,我们应该创建一个存储过程,该过程将生成唯一标识符并存储上面讨论的信息。 我们将这个存储过程称为“ LogNewExecution ”。 这是此功能的接口。 同样,可以根据您的需求进行定制。


PROCEDURE [LogNewExecution] (     @ExecutionName            VARCHAR(512),     @StartTime                DATETIME2,     @ExecutionId              <DATA_TYPE> OUTPUT,     @Debug                    BIT = 0  -- I always add @Debug parameter to my procedures-- to get extended information at execution
)

When the application runs, it will call that stored procedure and the application will get back the unique identifier of its execution thanks to the @ExecutionId parameter.

当应用程序运行时,它将调用该存储过程,并且由于@ExecutionId参数,该应用程序将获取其执行的唯一标识符。

The body of this procedure should contain a modified version of following query. This query essentially gets back information about caller and inserts it in conjunction with the value of @ExecutionName and @StartTime parameters.

该过程的正文应包含以下查询的修改版本。 该查询实质上是获取有关调用方的信息,并将其与@ExecutionName@StartTime参数的值一起插入。


INSERT into [ExecutionLog] (ExecutionName, SQLLogin, ClientNetAddress, ClientHostName, ClientProgramName, StartTime
)
SELECT@ExecutionName,s.login_name,c.client_net_address,s.[host_name],s.program_name,ISNULL(@StartTime,SYSDATETIME())
from sys.dm_exec_sessions s
left join sys.dm_exec_connections c
on s.session_id = c.session_id
WHERE s.session_id = @@spid
;

As you can see in sample code above, there is no value inserted for ExecutionParams column of ExecutionLog table. Actually, we could consider that an update should be run in application as we could log execution even before parameter validation. If it might not happen, you should add a @ExecutionParams parameter to LogNewExecution stored procedure.

如您在上面的示例代码中看到的,没有为ExecutionLog表的ExecutionParams列插入任何值。 实际上,我们可以考虑在应用程序中运行更新,因为即使在参数验证之前也可以记录执行情况。 如果可能不会发生,则应在LogNewExecution存储过程中添加@ExecutionParams参数。

When application execution completes, no matter the outcome, the application will simply run an update against the ExecutionLog table to set values to the appropriate columns regarding the outcome.

应用程序执行完成后,无论结果如何,应用程序都将仅对ExecutionLog表运行更新,以将值设置为与结果相关的适当列。

Following diagram summarizes what we discussed so far.

下图总结了到目前为止我们讨论的内容。

设计模式实现示例 (Design pattern implementation examples)

We will now review two implementations of that design pattern that I use very often. As you will see, each implementation is specialized to the situation it covers. Let’s just say for now that the first implementation is designed to be used in the context of reporting and the second in the context of script generation. We could also imagine other use cases like a monitoring and alerting tool, for example.

现在,我们将回顾我经常使用的该设计模式的两种实现。 正如您将看到的,每种实现都针对其所涉及的情况进行了专门化。 现在,让我们先说一下,第一个实现被设计为在报告的上下文中使用,第二个实现被设计为在脚本生成的上下文中使用。 我们还可以想象其他用例,例如监视和警报工具。

Implementation I: Generic Reporting Execution Log

实施方式I:通用报告执行日志

Before getting into the details of the design pattern implementation, let’s review what needs it will cover.

在详细介绍设计模式实现之前,让我们回顾一下它将满足的需求。

A while ago, I implemented an extended deadlock monitoring process that gets back deadlock XML graphs from Extended Events, stores it into a table and parses the XML to store extended details into another table. As soon as this process ends, we can run various reports as the occurrences by date or the most commonly implied application and so on. But we need to record these reports because we can’t keep all the collected deadlock XML graphs for obvious space consumption considerations.

不久前,我实现了扩展的死锁监视过程,该过程从扩展事件中获取死锁XML图,将其存储到表中,然后解析XML以将扩展的详细信息存储到另一个表中。 该过程结束后,我们可以按日期或最隐含的应用程序等形式运行各种报告。 但是我们需要记录这些报告,因为我们不能出于明显的空间消耗考虑而保留所有收集的死锁XML图。

But we could plan other kinds of reports than just deadlock reports, so let’s review some general facts about reporting:

但是我们可以计划其他报告,而不仅仅是死锁报告,因此让我们回顾一下有关报告的一些一般事实:

  • Reports can be stored either in a specialized table or in files on file system. 报表可以存储在专用表中,也可以存储在文件系统上的文件中。
  • Files can be based on structured formats like XML or HTML. It can also simply be a flat file or a CSV file. 文件可以基于XML或HTML之类的结构化格式。 它也可以只是平面文件或CSV文件。
  • The output target of a given reporting process can change from execution to execution. 给定报告过程的输出目标可以在执行之间变化。

This implies that output type and output path information have to be kept somewhere so that we are able to actually retrieve reports contents and process it.

这意味着输出类型和输出路径信息必须保留在某处,以便我们能够实际检索报告内容并进行处理。

Based on the description above, I specialized the design pattern presented in this article as follows.

基于以上描述,我专门介绍了本文中介绍的设计模式,如下所示。

Firstly, I extended the ExecutionLog table to add a ReportClass column so that I can filter records to only get reports related to deadlocks or whatever. I also added an OutputType and an OutputPath column. Here are two example usages of those two columns:

首先,我扩展了ExecutionLog表以添加一个ReportClass列,以便可以过滤记录以仅获取与死锁或其他相关的报告。 我还添加了OutputTypeOutputPath列。 这是这两列的两个示例用法:

  • OutputType is FILE/HTML and OutputPath is “C:\Public\report.html”
  • OutputTypeFILE / HTMLOutputPath“ C:\ Public \ report.html”
  • OutputType is TABLE and OutputPath is DBA.dbo.DeadlockReport
  • OutputTypeTABLEOutputPathDBA.dbo.DeadlockReport

In addition to those changes, I needed to define the way to uniquely identify a report. To do so, I simply used an IDENTITY column. I used BIGINT data type just in case I would use it a lot in future days.

除了这些更改之外,我还需要定义唯一标识报告的方式。 为此,我只使用了IDENTITY列。 我使用了BIGINT数据类型,以防万一我将来会经常使用它。

As I don’t think extended explanations on those columns are necessary, you will find below the T-SQL statement to create the actual ExecutionLog table:

由于我认为不需要在这些列上进行扩展说明,因此您将在T-SQL语句下面找到创建实际的ExecutionLog表的方法:


CREATE TABLE [Reporting].[ExecutionLog] ([ReportId]              BIGINT        NOT NULL IDENTITY(1,1),[ReportClass]           VARCHAR(512)  NULL,[ReportName]            VARCHAR(512)  NOT NULL,[SQLLogin]              VARCHAR(512)  NOT NULL,[ClientNetAddress]      VARCHAR(128)  NOT NULL,[ClientHostName]        VARCHAR(128)  NOT NULL,[ClientProgramName]     VARCHAR(256)  NOT NULL,[StartTime]             DATETIME2     NOT NULL,[EndTime]               DATETIME2     NULL,[OutputType]            VARCHAR(32)   NULL, -- TABLE / FILE / NONE[OutputPath]            VARCHAR(MAX)  NULL,[ReportParams]          VARCHAR(MAX)  NULL,[Outcome]               VARCHAR(64)   NULL,[ErrorDetails]          VARCHAR(MAX)  NULL
)

I also changed a little bit the LogNewExection procedure so that it takes the three new columns (ReportClass, OutputType and OutputPath).

我还稍微修改了LogNewExection过程,以便它采用了三个新列( ReportClassOutputTypeOutputPath )。


ALTER PROCEDURE [Reporting].[LogNewExecution] (@ReportClass                    VARCHAR(512) = NULL,@ReportName                     VARCHAR(512),@StartTime                      DATETIME2    = NULL,@OutputType                     VARCHAR(32),@OutputPath                     VARCHAR(MAX) = NULL,@ReportId                       BIGINT OUTPUT,@Debug                          BIT = 0
)

You will find attached to this article the script to create the schema, table and stored procedure presented in this section. You can run it against a test/dev database and test if it actually works as expected using following script.

您将在本文中找到本节中介绍的用于创建模式,表和存储过程的脚本。 您可以针对测试/开发数据库运行它,并使用以下脚本测试它是否按预期运行。


-- simulate application start
DECLARE @ReportId     BIGINT;
DECLARE @ProcSuccess  BIT = 0;
DECLARE @LineFeed     CHAR(2) = CHAR(13) + CHAR(10);
DECLARE @LogMsg       VARCHAR(MAX);
DECLARE @ProcParams   VARCHAR(MAX);EXEC [Reporting].[LogNewExecution] @ReportName  = 'TEST - Execution',@ReportClass = NULL,@ReportId    = @ReportId OUTPUT,@OutputType  = 'TABLE',@OutputPath  = '[master].[dbo].[ThisIsATestTbl]',@Debug       = 1
; -- For testing purpose :
SELECT * FROM Reporting.ExecutionLog ;-- Business logic code : parameters validation
-- Could set @ProcParams value on the flySET @ProcParams = '...' ;-- update ExecutionLog with process parameters
-- I didn't add this to LogNewExecution stored procedure as
-- this could be run before the end of parameter validationUPDATE Reporting.ExecutionLog
SET ReportParams = @ProcParams
WHEREReportId = @ReportId
;-- For testing purpose:
SELECT * FROM Reporting.ExecutionLog ;BEGIN TRY-- Procedure actual action (stores in report target)-- ...SET @ProcSuccess = 1;
END TRY
BEGIN CATCHSELECT @LogMsg = '/* ----------------------------- ( Details of the error caught during execution ) -----------------------------*/' + @LineFeed +'Error #' + CONVERT(VARCHAR(10),ERROR_NUMBER()) + ' with Severity ' + CONVERT(VARCHAR(10),ERROR_SEVERITY()) + ', State ' + CONVERT(VARCHAR(10),ERROR_STATE()) + @LineFeed +'in stored procedure ' + ISNULL(ERROR_PROCEDURE(),ISNULL(OBJECT_SCHEMA_NAME(@@PROCID) + '.' + OBJECT_NAME(@@PROCID),'N/A')) + @LineFeed +'Message:' + @LineFeed +ISNULL(ERROR_MESSAGE(),'N/A') + @LineFeed +'/* -------------------------- ( End of Details of the error caught during execution ) --------------------------*/' + @LineFeed;RAISERROR(@LogMsg,10,1);END CATCHUPDATE Reporting.ExecutionLog
SET Outcome = CASE WHEN @ProcSuccess = 1 THEN 'SUCCESS' ELSE 'ERROR' END,ErrorDetails = @LogMsg,EndTime      = SYSDATETIME()
WHERE ReportId = @ReportId
;-- For testing purpose:
SELECT * FROM Reporting.ExecutionLog ;

Here are the contents of the ExecutionLog table after execution began:

开始执行后,这是ExecutionLog表的内容:

Here are the contents of the ExecutionLog table after a failed execution:

这是执行失败后ExecutionLog表的内容:

Finally, the contents of the ExecutionLog table after a successful execution:

最后,成功执行后, ExecutionLog表的内容:

If we want to check what would happen if an error occurred, we can change following line:

如果我们想检查如果发生错误会发生什么,我们可以更改以下行:


SET @ProcSuccess = 1;

By

通过


RAISERROR('Test Error',12,1) ;

And we will get following view (that I split for better reading)

我们将获得以下观点(为了更好地阅读,我进行了拆分)

As we can see, the outcome is set to ERROR for second report. If we look at the ErrorDetails column, we see following message:

如我们所见,第二份报告的结果设置为ERROR 。 如果我们查看ErrorDetails列, 则会看到以下消息:

Implementation II: Generic script Generation Execution Log

实施二:通用脚本生成执行日志

Here, the aim is little different. I designed this execution log when I had to migrate databases from onr server to another for multiple SQL Server instances. The aim was initially to upgrade to a newer version of both Microsoft Windows Server and Microsoft SQL Server. Based on the criticality of machine and SQL Server edition, I could migrate via backup-restore, detach-attach or by setting up a database mirroring between source and destination then failover. Other migration solutions might come up in the future.

在这里,目标几乎没有什么不同。 当我不得不将数据库从另一台服务器迁移到另一个SQL Server实例时,我设计了该执行日志。 最初的目的是升级到Microsoft Windows Server和Microsoft SQL Server的较新版本。 基于计算机和SQL Server版本的重要性,我可以通过备份-还原,分离-附加或通过在源和目标之间建立数据库镜像然后进行故障转移来进行迁移。 将来可能会出现其他迁移解决方案。

While I could have written a bunch of scripts that I just call to run a particular aspect of migration, I wanted to keep control over what is done during migration and also to limit the possibilities if somebody eventually takes the scripts and runs it on a wrong server, some time after the original migration happened. So, I preferred to create a script generator. I divided the process into three steps:

虽然我可以编写一堆脚本来运行迁移的某个特定方面,但我想保持对迁移期间所做操作的控制,并且还希望限制某些人最终采用脚本并以错误方式运行它的可能性。服务器,原始迁移发生后的一段时间。 因此,我更喜欢创建一个脚本生成器。 我将过程分为三个步骤:

  • Migration parameters definition (which databases have to be migrated, from and to which server, which SQL Agent Jobs have to be migrated and so on). No logging needed. 迁移参数定义(必须从哪个数据库迁移到哪个数据库以及从哪个服务器迁移到哪个服务器,必须迁移哪个SQL Agent Job等)。 无需记录。
  • Generation of business logic for steps in migration process. This process will store in a table all the operations that need to be performed for actual migration. In this step, we focus on actual operations execution. There is no check for success of previous operation. So, we need to use a unique identifier for the execution. 为迁移过程中的步骤生成业务逻辑。 此过程将在表中存储实际迁移所需执行的所有操作。 在这一步中,我们专注于实际的操作执行。 没有检查先前操作是否成功。 因此,我们需要为执行使用唯一的标识符。
  • Generation of actual scripts for migration, which is based on the identifier of previous step, takes back the operations and generates either a T-SQL or PowerShell script with error handling between generated operations. This generation will look at the outcome of execution and will also check that it’s still relevant to generate scripts. 基于上一步的标识符,生成用于迁移的实际脚本,该脚本将撤回操作并生成T-SQL或PowerShell脚本,并在所生成的操作之间进行错误处理。 这一代将查看执行的结果,还将检查它与生成脚本是否仍然相关。

Based on the explanations above, we can quickly identify columns that have to be added to the ExecutionLog table presented as design pattern. There is actually only one column: ValidForNbDays. While this value can be seen as another parameter and could be put into the ExecutionParams column, it’s actually relevant to add this column as we want to easily check if the generated scripts would still be valid.

根据上面的解释,我们可以快速确定必须添加到以设计模式显示的ExecutionLog表中的列。 实际上只有一列: ValidForNbDays 。 尽管可以将该值视为另一个参数,并且可以将其放入ExecutionParams列中,但是添加此列实际上是相关的,因为我们希望轻松检查生成的脚本是否仍然有效。

You will find below the table that I use for this.

您将在我用于此的表格下面找到。


CREATE TABLE [SQLGeneration].[ExecutionLog] ([GenerationId]          BIGINT IDENTITY(1,1),[PurposeName]           [VARCHAR](512)  NOT NULL,[SQLLogin]              [VARCHAR](512)  NOT NULL,[ClientNetAddress]      [VARCHAR](128)  NOT NULL,[ClientHostName]        [VARCHAR](128)  NOT NULL,[ClientProgramName]     [VARCHAR](256)  NOT NULL,[StartTime]             [DATETIME]      NOT NULL,[EndTime]               [DATETIME]      NULL,[ValidForNbDays]        INT             NULL,[GenerationParams]      [VARCHAR](MAX)  NULL,[Outcome]               [VARCHAR](64)   NULL,[ErrorDetails]          [VARCHAR](MAX)  NULL
)

I also added a @NbDaysOfValidity to LogNewExecution stored procedure.

我还向LogNewExecution存储过程添加了@NbDaysOfValidity

We could review a testing batch like we did for previous example, but we won’t as it’s trivial to adapt this code to current implementation.

我们可以像前面的示例一样检查一个测试批处理,但是我们不会这样做,因为将代码修改为当前的实现很简单。

There are a lot of use cases that come to my mind in the field of generation that could use this table:

在生成领域,我想到了很多可以使用此表的用例:

  • Entire database objects scripts (for database versioning) 整个数据库对象脚本(用于数据库版本控制)
  • Database security export 数据库安全性导出
  • Particular database management tasks that could be automated like creating a test/dev instance, setting up database mirroring or Availability groups, etc 可以自动化的特定数据库管理任务,例如创建测试/开发实例,设置数据库镜像或可用性组等

结论 (Conclusion)

In this article, we’ve seen a standardized way to log execution of our processes. We’ve seen with two examples that it can be specialized to multiple fields and used in various situations.

在本文中,我们已经看到了记录过程执行情况的标准化方法。 通过两个示例,我们可以看到它可以专门用于多个领域,并可以在各种情况下使用。

资料下载 (Downloads)

  • Procedure Reporting LogNewExecution过程报告LogNewExecution
  • Procedure SQLGeneration LogNewExecution过程SQLGeneration LogNewExecution
  • Schema Reporting模式报告
  • Schema SQLGeneration模式SQLGeneration
  • Table Reporting ExecutionLog表报告执行日志
  • Table SQLGeneration ExecutionLog表SQLGeneration ExecutionLog

翻译自: https://www.sqlshack.com/a-t-sql-design-pattern-for-logging-process-execution/

t-sql执行结果

t-sql执行结果_用于记录流程执行的T-SQL设计模式相关推荐

  1. mysql 执行概况_转mysql源码分析之SQL执行过程简介

    本人打算从SQL语句的执行开始学习和分析MYSQL源码,首先了解MYSQL是如何执行一条SQL语句的,详细了解它的执行过程之后,再深入学习执行一条SQL语句的运行原理. 1)从执行一条SQL语句的堆栈 ...

  2. sql索引面试_关于索引的25个最佳SQL面试问答

    sql索引面试 Q1:堆表和群集表之间有什么区别? 我们如何确定该表是否为堆表? (Q1: What is the difference between a Heap table and a Clus ...

  3. sql azure 语法_在Azure Data Studio中计划SQL笔记本

    sql azure 语法 SQL Notebooks are an interactive way of creating documents, executing T-SQL queries alo ...

  4. sql server分布式_如何安装,配置和使用SQL Server分布式重播

    sql server分布式 介绍 (Introduction) The Microsoft SQL Server Distributed Replay feature has been provide ...

  5. cscript 执行代码_在Windows上执行恶意代码 by cscriptmshta

    Windows自带的可执行文件+合理构造的payload脚本=获得会话 cscript 简介 在cscript.exe来寻找和连接脚本的运行库,最常见的有VBScript和JavaScript. WS ...

  6. mysql 语句_如何记录MySQL执行过的SQL语句

    很多时候,我们需要知道 MySQL 执行过哪些 SQL 语句,比如 MySQL 被注入后,需要知道造成什么伤害等等.只要有 SQL 语句的记录,就能知道情况并作出对策.服务器是可以开启 MySQL 的 ...

  7. drop sql语句_用于从表中删除数据SQL Drop View语句

    drop sql语句 介绍 (Introduction) This guide covers the SQL statement for dropping (deleting) one or more ...

  8. sql datetime 排序_超全的数据库建表/SQL/索引规范,建议贴在工位上!

    作者:浮雷来源:juejin.im/post/6871969929365553165 「背景」 因为工作岗位的原因,负责制定了关于后端组数据库的规约规范,作为所有产品线的规范,历经几版的修改,最终形成 ...

  9. excel 复制数据 sql server 粘贴_一个Excel妙招,一个SQL技巧,解决批量数据插入问题

    #Excel技巧# #数据库# #MySQL# 业务背景 不知道您在工作中有没有遇到过这样几种情况: 业务定期给你一批数据结构相同的名单或者数据,要求你插入到库里并进行处理. 机器学习指标加工时,一个 ...

最新文章

  1. 《因果学习周刊》第5期:NeurIPS2021 因果发现最新进展
  2. 重磅推荐!机器学习|深度学习|自然语言处理 书籍/课程/资料/资源大分享!
  3. Academic English Reading Notes
  4. cmake linux编译,Ubuntu 16.04编译cmake源码
  5. android编译的错误日志,Android Studio:编译器错误输出窗口在哪里?
  6. android代码怎么打成蓝色,如何将我的Android应用程序的重音颜色从蓝色更改为其他颜色...
  7. 西瓜书《机器学习》多元线性回归公式推导
  8. python urlopen_Python爬虫教程-02-使用urlopen
  9. 如何将 Mac Dock 恢复到原始设置?
  10. c语言课设代写一般多少钱_海南彩礼钱一般给多少 海南娶媳妇要多少钱
  11. 如何彻底删除SQL 2005数据库(完整版)
  12. 2021最新Chrome 88版本 绕过webdriver检测
  13. 安装西门子博图一直重启_博图软件常见错误解决方法
  14. 接口自动化测试平台,Django“踩坑”之旅(四):“Not Found: /favicon.ico”错误处理
  15. 用cmd打开jar文件
  16. 百度顶会论文复现营论文心得
  17. Single Yuanz(单一原则)
  18. vue3运行npm run serve报错ERROR Error: Cannot find module ‘babel-plugin-import‘ Require stack:
  19. 31、查询 1990 年出生的学生名单
  20. python总结与习题(一)

热门文章

  1. python连接redis集群如何释放内存_python 连接redis集群
  2. 《程序员修炼之道》读后感02
  3. APIView和View的区别
  4. Python学习笔记(三)Python安装及设置环境变量
  5. $NOIp2018$劝退记
  6. PHP扩展插件 imagick 、PDO_MYSQL 安装
  7. ffmpeg rtmp 推流错误WriteN, RTMP send error 10053 10038
  8. windows linux—unix 跨平台通信集成控制系统----系统硬件信息获取
  9. 微软发布Sample Browser for Windows 8版:5000示例代码,触手可及
  10. 模拟新浪新闻在线聊天功能