【发布时间】:2019-05-11 08:20:20
【问题描述】:
在我的存储过程中,我创建了一个临时表以提高性能。
对于存储过程中的实际 select 语句,使用了几个标量 UDF,并且临时表替换了它们:
INSERT INTO #BEDRAGEN
SELECT
DD.ColumnA, DD.ColumnB, DD.ColumnC,
ISNULL(DBO.SIF_get_SalesAmount(DD.ColumnA, DD.ColumnB, DD.ColumnC), 0) AS Totaalbedrag,
FROM
T_InvoiceDetailDosDet as IDD
我的问题是:我想用代码替换 dbo.SIF_get_SalesAmount 或将标量 UDF 设置为表格 UDF,如果这样可以提高性能。
这个 UDF 中有什么:
返回金额。
它读取一个文件并计算几件事,然后得出一个总数。
函数有 3 个参数输入和 Amount 输出。
一块UDF:
ALTER FUNCTION [dbo].[SIF_get_SalesAmountDosDetail]
(@A VARCHAR(20),
@B VARCHAR(20),
@C VARCHAR(20)
)
RETURNS NUMERIC(12,2)
AS
DECLARE @SalesAmount NUMERIC(12,2)
, @SalesUnitOfAccount TINYINT
, @Unit NCHAR(5)
, @SalesUnit NCHAR(5)
, @TotalUnits NUMERIC(15, 3)
SELECT
@unit = p.Unit,
@SalesUnit = p.SalesUnit,
@SalesUnitOfAccount = dd.SalesUnitOfAccount
FROM
dbo.T_table p
WHERE
p.ColumnA = @A AND p.ColumnB = @B AND p.ColumnC = @C
SELECT @rc = @@ROWCOUNT
IF @rc <> 1
BEGIN
SELECT @SalesAmount = 0
RETURN @SalesAmount
END
IF @SalesUnit = 0
BEGIN
SELECT @SalesUnit = 1
END
-- several calculations follow based on values of @Unit etc.
-- at the end of the UDF:
-- last if then else calculation and then returning the Amount.
IF @SalesUnitOfAccount = 4
BEGIN
SELECT @PricePerDesc = @SalesUnit
SELECT @SalesAmount = CONVERT(numeric(12, 2), round((@CurrPrice * (@TotalSalesUnits / @SalesComputQty)) - @DiscAmount, 2))
END
SELECT @TotalSalesAmount = @TotalSalesAmount + ISNULL(@SalesAmount, 0)
-- Return the result of the function
RETURN @TotalSalesAmount
我可以通过什么方式在我的存储过程选择中插入此 UDF 代码?或者我可以用什么方法使它成为 UDF_table 函数?
感谢您的帮助。
【问题讨论】:
-
是的,用 UDF 的主体替换对标量 UDF 的调用,或者将 UDF 转换为内联表值 UDF 通常会大大提高性能。如果您能够将 UDF 的整个逻辑转换为单个
select语句,您可以试一试。将其转换为多步表值 UDF 是没有意义的。 -
谢谢。但我不知道如何将此逻辑与所有案例和计算放入单个选择语句中,该语句是用于填充#temp 表的子选择。你能指出我正确的方向吗?
-
有很多方法,它们都取决于你在做什么。我将首先以
with base_data as (SELECT p.Unit, case when p.SalesUnit = 0 then 1 else p.SalesUnit end as SalesUnit, dd.SalesUnitOfAccount FROM dbo.T_table p WHERE p.ColumnA = @A AND p.ColumnB = @B AND p.ColumnC = @C) select * from base_data的形式定义一个 CTE,使其根据需要返回其他计算列(例如case when dd.SalesUnitOfAccount = 4 then round((CurrPrice * (TotalSalesUnits / SalesComputQty)) - DiscAmount, 2) end,依赖于先前添加的计算列),然后从那里返回select。 -
谢谢,我会试一试。对 SQL 非常陌生,所以很挣扎。
标签: sql sql-server stored-procedures user-defined-functions