SQL Server 2014 UDF - 精简功能

Posted

技术标签:

【中文标题】SQL Server 2014 UDF - 精简功能【英文标题】:SQL Server 2014 UDF - Streamlining Function 【发布时间】:2015-03-26 02:06:09 【问题描述】:

我是一个开始自学 SQL/T-SQL 的新手。我一直在使用 SQL 2014 Express 并尝试通过编写 T-SQL 脚本来完成所有工作。我这样做是为了帮助一位朋友为她正在编写的真人游戏建立一个数据库,并且可以使用一些帮助来使以下用户定义的功能更加简化/以更正确的方式编写。

我认为该函数本身是必要的,因为需要持续计算以确定物品的经济价值。这似乎比尝试执行某种更新脚本(每次更新 Items 表时更新所有值)更好的方法。抱歉,如果这一切看起来很初级,请尝试学习。

下面是代码。我让它工作,我在我的开发数据库中得到它,它做了它应该做的事情。但我想清理它,我不知道该怎么做。

    CREATE FUNCTION dbo.ValueCalc (@itemid int)
    RETURNS INT
    AS
    BEGIN
    declare @rm1 int, @rm1amount int, @rm1value int,
    @rm2 int, @rm2amount int, @rm2value int,
    @rm3 int, @rm3amount int, @rm3value int,
    @rm4 int, @rm4amount int, @rm4value int,
    @cm1 int, @cm1amount int, @cm1value int,
    @cm2 int, @cm2amount int, @cm2value int,
    @cm3 int, @cm3amount int, @cm3value int,
    @cm4 int, @cm4amount int, @cm4value int,
    @productionvalue int;

    select @rm1 = MatReqs.RM1 FROM MatReqs WHERE MatReqs.ItemId = @itemid; 
    select @rm1amount = MatReqs.RM1Amount FROM MatReqs WHERE MatReqs.ItemId = @itemid; 
    select @rm1value = RawMats.BaseValue FROM RawMats WHERE RawMats.RawMatId = @rm1; 
    if (@rm1 IS NULL) set @rm1=0;
    if (@rm1amount IS NULL) set @rm1amount=0;
    if (@rm1value IS NULL) set @rm1value=0;

    Repeat the above 3 more times, for rm2, rm3, and rm4

    select @cm1 = MatReqs.CM1 FROM MatReqs WHERE MatReqs.ItemId = @itemid;
    select @cm1amount = MatReqs.CM1Amount FROM MatReqs WHERE MatReqs.ItemId = @itemid;
    select @cm1value = Items.ProdValue FROM Items WHERE Items.ItemId = @cm1;
    if (@cm1 IS NULL) set @cm1=0;
    if (@cm1amount IS NULL) set @cm1amount=0;
    if (@cm1value IS NULL) set @cm1value=0;

    same here, just removed the repetitions      

    set @productionvalue = (@rm1amount * @rm1value) 
    + (@rm2amount * @rm2value) 
    + (@rm3amount*@rm3value) 
    + (@rm4amount*@rm4value)
    + (@cm1amount*@cm1value)
    + (@cm2amount*@cm2value)
    + (@cm3amount*@cm3value)
    + (@cm4amount*@cm4value);

    set @productionvalue = @productionvalue + (@productionvalue * .15);

    return @productionvalue;
    END
    GO

【问题讨论】:

【参考方案1】:

如果我有一些示例数据和你想要的结果以及你的整个函数,我可以编写一个更有效的解决方案,因为 SQL Server 已针对基于集合的代码进行了优化,而你并没有真正使用它。就简单的清理而言,您可以这样做,但我宁愿您发布什么样本数据和所需的结果,让我为您提供一个基于集合的良好解决方案。

CREATE FUNCTION dbo.ValueCalc (@itemid INT)
RETURNS INT
AS
BEGIN
DECLARE @rm1 INT, @rm1amount INT, @rm1value INT,
        @rm2 INT, @rm2amount INT, @rm2value INT,
        @rm3 INT, @rm3amount INT, @rm3value INT,
        @rm4 INT, @rm4amount INT, @rm4value INT,
        @cm1 INT, @cm1amount INT, @cm1value INT,
        @cm2 INT, @cm2amount INT, @cm2value INT,
        @cm3 INT, @cm3amount INT, @cm3value INT,
        @cm4 INT, @cm4amount INT, @cm4value INT,
        @productionvalue INT;

--They both come from the same table with the where clause so just combine them
SELECT  @rm1 = ISNULL(MatReqs.RM1,0), 
        @rm1amount = ISNULL(MatReqs.RM1Amount,0)    
FROM MatReqs 
WHERE MatReqs.ItemId = @itemid; 

SELECT @rm1value = ISNULL(RawMats.BaseValue,0)  F
FROM RawMats 
WHERE RawMats.RawMatId = @rm1; 

--The ISNULL() function will take care of this
    --if (@rm1 IS NULL) set @rm1=0;
    --if (@rm1amount IS NULL) set @rm1amount=0;
    --if (@rm1value IS NULL) set @rm1value=0;


--Combine the first two statements again
SELECT  @cm1 = ISNULL(MatReqs.CM1,0),
        @cm1amount = ISNULL(MatReqs.CM1Amount,0)
FROM MatReqs 
WHERE MatReqs.ItemId = @itemid;

SELECT @cm1value = ISNULL(Items.ProdValue,0)
FROM Items 
WHERE Items.ItemId = @cm1;

--Again just use ISNULL
    --if (@cm1 IS NULL) set @cm1=0;
    --if (@cm1amount IS NULL) set @cm1amount=0;
    --if (@cm1value IS NULL) set @cm1value=0;

【讨论】:

以上是关于SQL Server 2014 UDF - 精简功能的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2008 - UDF 参数类型和返回类型

SQL Server用户自定义函数(UDF)

UDF 在 SQL Server 中调用外部 C++ 代码

在 SQL Server 2005 中创建 UDF 时出错

SQL Server 中 UDF 的动态表

SQL Server:结合 SELECT 和相关的 UDF 结果