如何为SQL Server创建用户定义的函数

时间:2014-09-06 02:07:27

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

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

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

它包含许多union子句,其语句如下图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))))

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

所以我认为对于UDF的id性能测试,我想出了下面的图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应用于原始查询时遇到各种各样的问题

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

注意:我确实知道用户定义的功能可能是一场性能噩梦,但即使在我可以测试的阶段也不行

由于

1 个答案:

答案 0 :(得分:1)

创建一个只包含一个名为order_id

的列的order_ids表
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
 ...