2013-01-12 53 views
0

版本1:我有一個「費」表數據庫設計 - 存儲條件規則?

FEE 
-Id 
-VariableAmount 
-FixedAmount 
-CurrencyCode 

當退出執行,取出系統對用戶的銀行賬戶等的錢,一個variableamount + fixedam​​ount費,每次交易收取費用。

版本2:我想,當滿足特定條件與一組收費規則實例進行充電,

Charge $0 when < $200 

Charge $3 when >= $200 

Charge $x when >= $Y 

我可以在我的web應用程序硬編碼,並且將工作,但我想成爲能夠在稍後改變它,當將這些條件存儲在數據庫中時,你將如何設計它?

費用1. * FEE_RULE ??你在數據庫中存儲什麼?

+0

當規則改變我會改變我的代碼並重新部署。這對你有可能嗎? – usr

+0

@usr它現在可以工作:) – 001

回答

2

你描述的是一個規則引擎。 SQL Server沒有內置的內容,但MSDN上有一篇關於如何構建自己的文章。它可能看起來有點過度設計一個規則,但也許你的應用程序也有其他規則。 Find out more.

2

你總是可以把這個業務邏輯在負責執行撤離的存儲過程。這樣,當你想改變邏輯時,你不必重新部署Web應用程序。

0

我的辦法,最簡單的形式,會是這樣的下面。

USE tempdb 
GO 
IF OBJECT_ID('tempdb.dbo.Transactions') IS NOT NULL DROP TABLE Transactions 

SELECT TOP 500 TxnVal = ABS(CHECKSUM(NEWID())) % 1000 
INTO Transactions 
FROM sys.columns 

;WITH Fee (Id, VariableAmountFloor, VariableAmountCeiling, VariableAmount, FixedAmount, CurrencyCode) AS 
(
    SELECT 1, 0, 200,  0.8, 0.1, 'x' UNION ALL 
    SELECT 2, 201, 300,  0.65, 0.1, 'x' UNION ALL 
    -- NB: have chosen 2147483647 as the ceiling because it is the maximum value of the INT type 
    -- You will probably have some sort of float 
    SELECT 3, 301, 2147483647, 0.4, 0.1, 'x' 
) 
SELECT T.TxnVal 
     ,VariableFee = F.VariableAmount 
     ,FixedFee  = F.FixedAmount 
     ,TxnPlusCosts = T.TxnVal + F.VariableAmount + F.FixedAmount 
FROM Transactions T 
JOIN Fee   F ON T.TxnVal BETWEEN F.VariableAmountFloor AND F.VariableAmountCeiling 
0
SET ANSI_WARNINGS ON; 
GO 

--DROP TABLE dbo.FeeInterval 
CREATE TABLE dbo.FeeInterval (
    FeeIntervalID INT IDENTITY(1,1),  
     CONSTRAINT PK_FeeInterval PRIMARY KEY (FeeIntervalID), 

    StartValue NUMERIC(18,2) NOT NULL, 
     CONSTRAINT CK_FeeInterval_StartValue CHECK (StartValue > 0), 
    -- If EndValue IS NOT NULL Then the interval is TxValue BETWEEN [StartValue, EndValue] 
    -- Else (EndValue IS NULL) Then the interval is TxValue >= StartValue 
    -- Also, you should check is this intervals are continuous (using a trigger) 
    -- and only the last EndValue IS NULL 
    EndValue NUMERIC(18,2) NULL, -- Allow null, 
     CONSTRAINT CK_FeeInterval_StartDate_EndDate CHECK (StartValue < EndValue), 
    VariableAmount NUMERIC(18,2) NOT NULL, 
    FixedAmount NUMERIC(18,2) NOT NULL 
); 
-- + CREATE INDEX ... 
GO 

--DROP TABLE dbo.[Transaction] 
CREATE TABLE dbo.[Transaction] (
    TransactionID INT IDENTITY(1,1), 
     CONSTRAINT PK_Transaction PRIMARY KEY (TransactionID), 
    TransactionDate DATE NOT NULL 
     CONSTRAINT DF_Transaction_TransactionDate DEFAULT GETDATE(), 
    -- You should check (using a trigger) if there is an applicable fee for this TxnValue 
    --  If the last EndValue IS NOT NULL Then TxnValue BETWEEN MIN(StartDate) AND MAX(EndValue) 
    --  Else (the last Endvalue IS NULL Then TxnValue >= MIN(StartDate) 
    TxnValue NUMERIC(18,2) NOT NULL 
    -- Also, you should store the FeeIntervalID used for every transaction 
    -- FeeIntervalID INT NOT NULL 
    -- and (maybe) VariableAmount/FixedAmount/TxnPlusCosts NUMERIC(18,2) NOT NULL 
) 
GO 

INSERT dbo.FeeInterval (StartValue, EndValue, VariableAmount, FixedAmount) 
SELECT 0.01, 200,  0.8, 0.1 UNION ALL -- 0.01 because data type is NUMERIC(,2) 
SELECT 201, 300,  0.65, 0.1 UNION ALL 
SELECT 301, NULL,  0.4, 0.1; 
GO 

INSERT dbo.[Transaction] (TxnValue) 
SELECT 0.01 UNION ALL 
SELECT 50 UNION ALL 
SELECT 200 UNION ALL 
SELECT 250 UNION ALL 
SELECT 350 UNION ALL 
SELECT -0.01; -- Wrong value 
GO 

--DROP FUNCTION dbo.GetApplicableFee 
CREATE FUNCTION dbo.GetApplicableFee(@TxnValue NUMERIC(18,2)) 
RETURNS TABLE 
AS 
RETURN 
SELECT s.FeeIntervalID, s.VariableAmount, s.FixedAmount, @TxnValue + s.VariableAmount + s.FixedAmount AS TxnPlusCosts 
FROM (
    SELECT i.FeeIntervalID, i.VariableAmount, i.FixedAmount, 
      i.StartValue, i.EndValue, 
      ROW_NUMBER() OVER(ORDER BY i.StartValue DESC) RowNum 
    FROM dbo.FeeInterval i 
) s 
WHERE @TxnValue BETWEEN s.StartValue AND s.EndValue AND s.RowNum > 1 
OR  @TxnValue >= s.StartValue AND s.RowNum = 1 
GO 

SELECT *, 
     CASE WHEN f.FeeIntervalID IS NOT NULL THEN 'TxnValue with applicable fee' ELSE 'Wrong TxnValue' END AS [Description] 
FROM dbo.[Transaction] txn 
OUTER APPLY dbo.GetApplicableFee(txn.TxnValue) f 
-- or 
SELECT *, 
     (SELECT f.TxnPlusCosts FROM dbo.GetApplicableFee(txn.TxnValue) f) AS TxnPlusCosts 
FROM dbo.[Transaction] txn 

如果您有任何疑問,請隨時問。