【问题标题】:How to create a User Defined Function for SQL server如何为 SQL Server 创建用户定义函数
【发布时间】:2014-09-06 02:07:26
【问题描述】:

不过,这是一个相当温和的问题

我有一个相当大的存储过程,我正在尝试简化它以提高可读性

它包含许多带有如下图1所示语句的联合子句

图1

SELECT COUNT(1) AS Total
  FROM Orders 
  WHERE (NOT EXISTS (
      SELECT 1 
        FROM (
          SELECT Id 
            FROM OrderLineItems 
            WHERE Orders.Id = Order_Id) AS Sub
        WHERE EXISTS (
            SELECT 1 
              FROM NormalizedLineItems 
              WHERE (Sub.Id = OrderLineItem_Id)
                AND (OutOfStock = 1))))
    AND (EXISTS (
      SELECT 1 AS Total
        FROM OrderShipments 
        WHERE (Orders.Id = Order_Id)
          AND (CarrierApproved = 0)))
    AND (IsQuote = 0)
    AND (Cancelled = 0)
    AND (Archived = 0)
    AND (Completed = 0)
    AND (Holding = 0)

但是每个语句中都有很多重复出现的模式

以下模式多次出现图2

图2

  WHERE (NOT EXISTS (
      SELECT 1 
        FROM (
          SELECT Id 
            FROM OrderLineItems 
            WHERE Orders.Id = Order_Id) AS Sub
        WHERE EXISTS (
            SELECT 1 
              FROM NormalizedLineItems 
              WHERE (Sub.Id = OrderLineItem_Id)
                AND (OutOfStock = 1))))

我试图(出于可读性目的)减少主存储过程中的代码

所以我认为id性能测试是一个UDF,我想出了下面的图3

图3

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION TestFunction (@OrderId int)
RETURNS TABLE
AS
  RETURN
  (
  -- Add the SELECT statement with parameter references here
  SELECT 1 AS Total
    FROM (
      SELECT OrderLineItems.Id AS Id
        FROM OrderLineItems
        WHERE @OrderId = Order_Id) AS Sub
    WHERE EXISTS (
        SELECT 1 AS Total
          FROM NormalizedLineItems
          WHERE (Sub.Id = OrderLineItem_Id)
            AND (OutOfStock = 1)))
GO

尽管上述所有编译,我不确定我是否在正确的轨道上,我在尝试将上述 UDF 应用于原始查询时遇到各种问题

我想知道是否有人可以给我一个具体示例,说明如何将 Fig.2 从 Fig.1 抽象为 UDF,这样我至少可以对解决方案进行性能测试,看看它是否值得

注意:我知道用户定义的函数可能是一场性能噩梦,但我什至还没有到可以测试的阶段

谢谢

【问题讨论】:

  • 这可能是使用 UDF 来简化 where 子句中的代码的最后选择。对可重用数据使用 CTE 或常规表是一种很好的做法。或者EXEC不同段sql语句串组合的动态查询。
  • 感谢您的 cmets 和回答,病态研究您提出的观点,并测试您的代码,让我深思

标签: sql sql-server tsql user-defined-functions


【解决方案1】:

创建一个 order_ids 表,其中只有一个名为 order_id 的列

Insert into order_ids
select order_id from 
  FROM Orders 
  WHERE (NOT EXISTS (
      SELECT 1 
        FROM (
          SELECT Id 
            FROM OrderLineItems 
            WHERE Orders.Id = Order_Id) AS Sub
        WHERE EXISTS (
            SELECT 1 
              FROM NormalizedLineItems 
              WHERE (Sub.Id = OrderLineItem_Id)
                AND (OutOfStock = 1))))

然后你可以像这样简化你的Sql:

SELECT COUNT(1) AS Total
  FROM Orders 
  join order_ids
  on order_ids.order_id = Orders.order_id
 ...

如果您的重复语句仅在一个查询中, Common Table Expression是最好的选择:

with CTE_order_ids as
(select order_id from 
  FROM Orders 
  WHERE (NOT EXISTS (
      SELECT 1 
        FROM (
          SELECT Id 
            FROM OrderLineItems 
            WHERE Orders.Id = Order_Id) AS Sub
        WHERE EXISTS (
            SELECT 1 
              FROM NormalizedLineItems 
              WHERE (Sub.Id = OrderLineItem_Id)
                AND (OutOfStock = 1))))
)
SELECT COUNT(1) AS Total
  FROM Orders 
  join CTE_order_ids 
  on order_ids.order_id = Orders.order_id
 ...

【讨论】:

  • 谢谢你,我已经测试过了,它也给了我很好的性能好处
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-30
  • 2016-11-25
  • 2019-06-10
相关资源
最近更新 更多