作为计算列的一部分的标量函数

Scalar function as a part of computed column

我正在使用 SQL Server 2012。我想创建一个带有计算列的 table。此列是此 table 中各列的总和,但我需要将总和乘以增值税 table 中的增值税税率以获得含税的总值。增值税值每月插入到增值税 table 中,并作为 smallint 存储在 Stawka 列中(英文意思是 "Rate")。 table Prąd 的值每个月也会插入,因此我需要使用 VAT table.

中 Stawka 列的当前增值税税率

因此,如果税率(VAT 中的 Stawka 列 table)当前为 23%,这是简单的数学运算: (Y+Z) + 23% * (Y+Z) =( Y+Z) * (1 + 0.23) = (Y+Z) * 1.23 其中 Y+Z 是 table 公关

来自 table Prąd 的行示例。在最后一列(计算列)下方,它只是 0.2661 + 0.2103 的总和。所以如上所述,首先我需要将 0.2103 和 0.2661 相加,然后将总和乘以 1.23:

ID  Data    Rok Kwartał Miesiąc Dzień   Jednostka   Odczyt  Zużycie Energia elektryczna czynna  Opłata dystrybucyjna zmienna Stawka jednostkowa energii
1 2015-01-01 2015   1     1      1        kWh        300      20         0.2661                    0.2103                            0.4764

我无法对值 1.23 进行硬编码,因为增值税税率可能会发生变化,因此我决定创建增值税 table 但我不知道如何在计算列内的 Stawka 列中使用这些值。

我尝试使用我在此处找到的一些技巧并使用标量函数来获取当前 VAT 值并进行连接,但似乎我无法将其用作整个计算的一部分。下面的一些代码:

Table 我正在尝试创建计算列(创建 table 时弹出错误无效列 "Stawka"):

    CREATE TABLE dbo.Prąd
(
ID INT NOT NULL IDENTITY (1,1),
Data DATE NOT NULL,
Rok AS YEAR(Data) PERSISTED NOT NULL,
Kwartał AS DATEPART(q,Data) PERSISTED NOT NULL,
Miesiąc AS MONTH(Data) PERSISTED NOT NULL,
Dzień AS DAY(Data) PERSISTED NOT NULL,
Jednostka VARCHAR (5) NULL,
Odczyt SMALLINT NOT NULL,
Zużycie SMALLINT NOT NULL,
[Energia elektryczna czynna] DECIMAL (9,4) NULL,
[Opłata dystrybucyjna zmienna] DECIMAL (9,4) NULL,
[Stawka jednostkowa energii] AS CAST (([Energia elektryczna czynna] + [Opłata dystrybucyjna zmienna])*('1.' + dbo.fnVAT(ID)) AS DECIMAL (9,4)) PERSISTED NOT NULL
)

增值税table:

CREATE TABLE dbo.VAT
(
ID INT NOT NULL IDENTITY (1,1),
Data DATE NOT NULL,
Stawka SMALLINT NOT NULL,
);

标量函数:

CREATE FUNCTION fnVAT (@VAT SMALLINT)

RETURNS SMALLINT

AS BEGIN

SELECT @VAT = Stawka FROM VAT AS V JOIN Prąd AS P ON V.ID = P.ID

RETURN @VAT

END

由于增值税取决于另一个 table 的内容,我认为不可能将该列创建为持久的。这意味着每次 select 该列时,都会为 select 中的每一行分别调用标量函数。这对性能来说真的很糟糕,我真的不能推荐它,但如果你想这样做,这是这样做的方法:

CREATE FUNCTION fnVAT (@DATE date)    
RETURNS decimal(3,2)    
AS BEGIN
    declare @VAT smallint

    SELECT top 1 @VAT = VAT FROM VAT where Date <= @DATE order by DATE desc 

    RETURN 1 + 0.01 * @VAT
END;

alter table Prad add VAT AS (Value1 + Value2) * dbo.fnVAT(Date)

我的示例是使用此 table:

CREATE TABLE Prad
    ([ID] int, [Date] date, [Value1] DECIMAL (9,4), [Value2] DECIMAL (9,4))

因为我认为不使用波兰语 (?) 列名称会容易得多。

SQL Fiddle

中的示例

就像你说的,你也可以在触发器中执行此操作,这在性能方面应该会好很多,因为提取只进行一次,而且由于 VAT 不会经常改变,所以它可能是最好的想法。