In this article, we will learn multi-statement table-valued functions (MSTVFs) basics and then we will reinforce our learnings with case scenarios.

在本文中,我们将学习多语句表值函数(MSTVF)的基础知识,然后我们将通过案例场景来加强学习。

At first, If you are a newbie about the SQL Server functions concept, I would suggest taking a glance at the following two articles before to start this one:

刚开始时,如果您是有关SQL Server函数概念的新手,建议您在开始本文之前先阅读以下两篇文章:

  1. How to use SQL Server built-in functions and create user-defined scalar functions 如何使用SQL Server内置函数和创建用户定义的标量函数
  2. SQL Server inline table-valued functions SQL Server内联表值函数

我们为什么使用这些功能 (Why we use the functions)

With the help of the functions, we can encapsulate the codes and we can also equip and execute these code packages with parameters.

借助这些功能,我们可以封装代码,还可以为参数代码装备并执行这些代码包。

Don’t Repeat Yourself (DRY) is a software development approach which advises that “as much as possible, don’t rewrite the same code again”. The main idea of this approach is to reduce code repetition. The main advantages of this idea are:

不要重复自己( DRY )是一种软件开发方法,建议“尽可能,不要再重写相同的代码”。 这种方法的主要思想是减少代码重复。 这个想法的主要优点是:

  • Improve maintainability 改善可维护性
  • Improve the code readability 提高代码可读性

If we want to gain these benefits in SQL Server, the user-defined functions come at the first point in the list in order to implement this idea.

如果我们想在SQL Server中获得这些好处,则用户定义的函数位于列表的第一位,以实现这一思想。

In the following section, we will go through with MSTVFs basics and usage scenarios.

在下一节中,我们将介绍MSTVF的基础知识和使用场景。

说明和语法: (Description and syntax:)

Multi-statement table-valued function returns a table as output and this output table structure can be defined by the user. MSTVFs can contain only one statement or more than one statement. Also, we can modify and aggregate the output table in the function body. The syntax of the function will be liked to the following :

多语句表值函数返回一个表作为输出,并且该输出表结构可由用户定义。 MSTVF只能包含一个语句,也可以包含多个语句。 同样,我们可以在函数体中修改和聚合输出表。 该函数的语法如下所示:

CREATE FUNCTION MultiStatement_TableValued_Function_Name
(@param1 DataType,@param2 DataType,@paramN DataType
)
RETURNS
@OutputTable TABLE
(@Column1 DataTypeForColumn1 ,@Column2 DataTypeForColumn2
)
AS
BEGIN--FunctionBody
RETURN
END

MSTVFs, apparent differences from the inline table-valued function can be listed as follows;

MSTVF,很明显 与内联表值函数的差异可以列出如下;

  • Declaring the return table structure 声明返回表结构
  • BEGIN/END block BEGIN / END块开头和结尾
  • The function body can involve one or more than one statement 函数主体可以包含一个或多个语句
  • RETURN operator RETURN运算符

The below image illustrates the syntax differences between multi-statement and inline table-valued functions.

下图说明了多语句和内联表值函数之间的语法差异。

创建多语句表值函数(MSTVF) ( Creating a multi-statement table-valued function (MSTVF))

In this section, we will work on a case scenario and overcome the issue with MSTVF.

在本节中,我们将处理一个案例场景并克服MSTVF的问题。

Note: All the examples of this article will be used to the Adventureworks sample database

注意:本文的所有示例都将用于Adventureworks示例数据库

Scenario: Suppose that, the production engineers want to analyze product scrap quantities and they determine a critical value in order to degrade the cost of the products. If the scrap quantities exceed this value, the query has to indicate these product’s scrap status as critical. Furthermore, the value that determines the scrap status might be changed according to the production situation. The production engineers sent a draft output of the query in order to illustrate which columns they want to see in the output of the query.

场景:假设生产工程师想要分析产品的报废数量,并确定一个临界值以降低产品的成本。 如果报废数量超过该值,则查询必须指出这些产品的报废状态为严重。 此外,确定废品状态的值可能会根据生产情况而改变。 生产工程师发送了查询的草稿输出,以说明他们希望在查询的输出中查看哪些列。

For this scenario, we can develop a multi-statement table-valued function. Through the following query, we can overcome this issue:

对于这种情况,我们可以开发一个多语句表值函数。 通过以下查询,我们可以解决此问题:

CREATE FUNCTION dbo.UdfGetProductsScrapStatus
(
@ScrapComLevel INT
)
RETURNS @ResultTable TABLE
(
ProductName VARCHAR(50), ScrapQty FLOAT, ScrapReasonDef VARCHAR(100), ScrapStatus VARCHAR(50)
) AS BEGININSERT INTO @ResultTableSELECT PR.Name, SUM([ScrappedQty]), SC.Name, NULLFROM [Production].[WorkOrder] AS WOINNER JOIN Production.Product AS PRON Pr.ProductID = WO.ProductIDINNER JOIN Production.ScrapReason AS SCON SC.ScrapReasonID = WO.ScrapReasonIDWHERE WO.ScrapReasonID IS NOT NULLGROUP BY PR.Name, SC.Name
UPDATE @ResultTableSET ScrapStatus = CASE WHEN ScrapQty > @ScrapComLevel THEN 'Critical'ELSE 'Normal'ENDRETURN
END

In the above function, we declared a parameter (@ScrapComLevel). According to this parameter, the scrap quantity status determined as critical or normal. The return table (@ResultTable) contains ProductName, ScrapQty, ScrapReasonDef, and ScrapStatus columns and this table will be populated and updated in the function body according to the parameter value. Finally, it returns the output table as a resultset. The function body is placed between the BEGIN/END block and whole statements will be executed within this block. We must use the RETURN statement in order to return the output table.

在上面的函数中,我们声明了一个参数( @ScrapComLevel )。 根据此参数,废料数量状态确定为严重或正常。 返回表( @ResultTable )包含ProductName,ScrapQty,ScrapReasonDef和ScrapStatus列,并且该表将根据参数值在函数主体中进行填充和更新。 最后,它返回输出表作为结果集。 函数体位于BEGIN / END块之间,整个语句将在此块内执行。 我们必须使用RETURN语句才能返回输出表。

After the creation of the function, we can see the UdfGetProductsScrapStatus function under the Programility folder in SQL Server Management Studio.

创建函数后,我们可以在Programility文件夹下看到UdfGetProductsScrapStatus函数 在SQL Server Management Studio中。

As you can see in the above image, SSMS also shows the parameter details of the UdfGetProductsScrapStatus function.

如上图所示,SSMS还显示了UdfGetProductsScrapStatus函数的参数详细信息。

执行多语句表值函数: (Executing a multi-statement table-valued function:)

With the help of the following query, we can execute the UdfGetProductsScrapStatus function so that we can obtain the requested result set by the engineering team.

借助以下查询,我们可以执行UdfGetProductsScrapStatus函数,以便我们获得工程团队要求的结果集。

SELECT ProductName AS [Product Name],ScrapQty AS [Scrap Quantity] , ScrapReasonDef AS [Scrap Reason],ScrapStatus AS [Scrap Status]
FROM dbo.UdfGetProductsScrapStatus(200)

交叉应用和多语句表值函数: (CROSS APPLY and multi-statement table-valued function:)

Scenario: The production engineers made a new request after completing the works about the scrap issues. They decided to determine a safe level scrap value for all scrap reasons and they wanted to compare this value to total scrap quantities.

场景:生产工程师在完成有关报废问题的工作后提出了新的要求。 他们决定出于所有废料原因确定安全水平的废料值,并希望将该值与废料总量进行比较。

For this scenario, we should create a new function and it should accept a parameter that filters the ScrapReasonID column. On the other hand, we can pass the whole scrap reason values in the Production.ScrapReason table with the help of the CROSS APPLY operator. CROSS APPLY operator invokes the table-valued function for each row of the Production.ScrapReason and populates the result set if the table-valued function returns a result. At first, we should add a new column to the Production.ScrapReason and update the values.

对于这种情况,我们应该创建一个新函数,并且应该接受一个过滤ScrapReasonID列的参数。 另一方面,我们可以在CROSS APPLY运算符的帮助下在Production.ScrapReason表中传递整个报废原因值。 如果表值函数返回结果,则CROSS APPLY运算符将为Production.ScrapReason的每一行调用表值函数,并填充结果集。 首先,我们应该在Production.ScrapReason中添加一个新列并更新值。

ALTER TABLE Production.ScrapReason ADD  SafeLevel INT
GO
UPDATE Production.ScrapReason SET SafeLevel=CAST(RAND()*100*ScrapReasonID AS int)

In this step, we will create a new MSTVF.

在此步骤中,我们将创建一个新的MSTVF。

CREATE FUNCTION dbo.UdfGetProductsScrapStatusbyID
(
@ScrapQty INT , @ScrapID INT
)
RETURNS @ResultTable TABLE
(
ProductName VARCHAR(50), ScrapQty FLOAT,  ScrapStatus VARCHAR(50)
) AS BEGININSERT INTO @ResultTableSELECT PR.Name, SUM([ScrappedQty]), NULLFROM [Production].[WorkOrder] AS WOINNER JOIN Production.Product AS PRON Pr.ProductID = WO.ProductIDWHERE WO.ScrapReasonID IS NOT NULL AND WO.ScrapReasonID=@ScrapIDGROUP BY PR.Name
UPDATE @ResultTableSET ScrapStatus = CASE WHEN ScrapQty > @ScrapQty THEN 'Critical'ELSE 'Normal'ENDRETURN
END

Now we will join Production.ScrapReason to UdfGetProductsScrapStatusbyID through the CROSS APPLY operator.

现在,我们将通过CROSS APPLY运算符将Production.ScrapReason加入UdfGetProductsScrapStatusbyID

SELECT Name AS [Scrap Reason],
SafeLevel AS [Acceptable Quantity],
ProductName AS [Product Name],
ScrapQty AS [Scrap Quantity],
ScrapStatus AS [Scrap Status],
IIF(ScrapQty > SafeLevel, 'Pass', 'Fail') AS [Status]
FROM(SELECT *FROM Production.ScrapReason AS SCCROSS APPLYdbo.UdfGetProductsScrapStatusbyID( 100, SC.ScrapReasonID )) AS TMP_TBL;

结论 (Conclusion)

The main benefit of the multi-statement table-valued functions enables us to modify the return/output table in the function body so that we can generate more complicated resultset. Also, we can easily use this function return table in the SELECT statements and can be joined to other tables.

多语句表值函数的主要好处是使我们能够修改函数主体中的返回/输出表,从而可以生成更复杂的结果集。 另外,我们可以在SELECT语句中轻松使用此函数返回表,并且可以将其连接到其他表。

翻译自: https://www.sqlshack.com/sql-server-multi-statement-table-valued-functions/

SQL Server多语句表值函数相关推荐

  1. SQL Server内联表值函数

    In this article series, we will find basics and common usage scenarios about the inline table-valued ...

  2. SQL server内嵌表值函数与多语句表值函数

    内联表值函数 create function 函数名(@变量 as 类型) returns table as return ( 结果集[select查询语句] ) go select 列名 from ...

  3. mysql 实现表值函数,SQL SERVER 的 CLR表值函数

    一.使用CLR表值 函数 的背景 在SQL SERVER里面,直接读取远程 数据库 的表,似乎会占用大量的内存,出现类似错误: 链接服务器 192.168.0.1 的 OLE DB 访问接口 SQLN ...

  4. sql多语句表值函数_构造一个特殊的多语句表函数来检查SQL Server的运行状况

    sql多语句表值函数 问题 ( The Problem ) Checking the many SQL Servers health conditions is one of the DBA basi ...

  5. SQL Server中的STRING_SPLIT函数

    This article will cover the STRING_SPLIT function in SQL Server including an overview and detailed u ...

  6. sqlserver 指定的网络名不再可用_50个比较实用的SQL Server查询语句(1)

    在本文中,我将解释一些通用的SQL查询.我认为每个开发人员都应该了解这些查询.这些查询与SQL的任何特定主题都无关.但是了解这些查询可以解决一些复杂的任务,并且可以在许多场景中使用. 查询1:检索所有 ...

  7. 了解SQL Server CASE语句

    SQL Server CASE statement is equivalent to the IF-THEN statement in Excel. SQL Server CASE语句等效于Excel ...

  8. 学习SQL:SQL Server日期和时间函数

    So far, we haven't talked about SQL Server date and time functions. Today we'll change that. We'll t ...

  9. sql raiserror_SQL Server PRINT和SQL Server RAISERROR语句

    sql raiserror This article explores the SQL Server PRINT statements, and its alternative SQL Server ...

最新文章

  1. 浅析网站优化工作具体包括哪些内容?
  2. 软件项目组织管理(四)项目集成管理
  3. 数据结构 - 最小堆最大堆
  4. JEECG Online Coding 开发流程
  5. Java 中的细节补充
  6. [EffectiveC++]item06:若不想使用编译器自动生成的函数,就该明确决绝
  7. Microsoft SQL Server 2008技术内幕:T-SQL查询---------逻辑查询处理
  8. 【MYSQL笔记】MYSQL监视器
  9. 2017中国云计算开源优秀案例
  10. 如何实现一个HTML5 RPG游戏引擎——第二章,实现烟雨和雪飞效果
  11. Python根据歌曲id爬取网易云音乐歌词
  12. 运放 - 输出阻抗(Open loop output resistance)Ro
  13. 搜索引擎都有哪几种类型?
  14. Arduino使用烟雾传感器
  15. 希望各位dalao不吝赐教
  16. mysql查男女比例百分比_sql server 计算男女比例 百分比
  17. http代理IP的API接口要怎么使用
  18. C#面向对象程序设计课程实验五:实验名称:C#面向对象技术
  19. 微信小程序app.js给全局变量globalData赋值
  20. 金蝶K3wise、金蝶KIS旗舰版数据同步到金蝶云星空

热门文章

  1. 华为ModelArts自定义镜像(PyTorch镜像)
  2. 12、Bootstrap和ServerBootstrap啥关系
  3. 自主开发的遥感图像数据处理系统
  4. mysql增加列耗时_实战-130W表增加字段耗时
  5. 网络学习 DNS服务:域名解析和域名迁徙
  6. 中国也曾有过贵族:春秋战国是其黄金时期
  7. asu计算机科学排名,美本ASU计算机专业申硕圆梦Top前30名校
  8. DTAS-电机机壳与端盖止口垂直度对电机气隙影响
  9. python携带cookie登陆
  10. python培训学校-上海python培训学校