2012-09-08 38 views
1

我正在創建一個假股票市場類型數據庫,而Transaction表需要某種邏輯來執行某些規則。下面是Transaction表我使用的是:在股票交易表中執行規則

Id AccountId Action Qty Price Amount 
1 1   SELL 30 $1.00 $30.00 
2 2   BUY  30 $1.00 -$30.00 
3 1   SELL 20 $2.00 $40.00 
4 3   BUY  20 $2.00 -$40.00 
5 3   DEPOSIT   $100.00 

正如你可以在這裏看到BUY/SELL操作必須有一個QtyPrice,並應計算的Amount。存款行動不需要QtyPrice,因爲那只是一個用戶把錢存入Account

我正在考慮使用某種觸發器來做到這一點。有更好的做法嗎?

+0

Imo a [check constraint](http://msdn.microsoft.com/zh-cn/library/ms188258(v = sql.105).aspx)將會更好。 – StuartLC

+1

由於購買,銷售和存款有不同的要求,人們可能會爭辯說,您應該使用適合每個要求的獨立表格。這會[規範化](http://en.wikipedia.org/wiki/Database_normalization)設計,並允許列的簡單約束。如果你想要防止賣空股票,即賣出你沒有持有的股票,那麼觸發器是合適的。 – HABO

+0

@HABO - 這種類型的東西有特定的模式嗎?我感覺好像所有事務的單個表是最有意義的,因爲我有其他表引用它。我還爲賬戶表設置了一個觸發器設置,用於更新餘額 – Ryan

回答

1

測試在SQL Server 2012(股票符號省略。)

create table stock_transactions (
    trans_id integer primary key, 
    trans_ts datetime not null default current_timestamp, 
    account_id integer not null, -- references accounts, not shown 

    -- char(1) keeps the table narrow, while avoiding a needless 
    -- join on an integer. 
    -- (b)uy, (s)ell, (d)eposit 
    action char(1) not null check (action in ('b', 's', 'd')), 

    qty integer not null check (qty > 0), 

    -- If your platform offers a special data type for money, you 
    -- should probably use it. 
    price money not null check (price > cast(0.00 as money)), 

    -- Assumes it's not practical to calculate amounts on the fly 
    -- for many millions of rows. If you store it, use a constraint 
    -- to make sure it's right. But you're better off starting 
    -- with a view that does the calculation. If that doesn't perform 
    -- well, try an indexed view, or (as I did below) add the 
    -- "trans_amount" column and check constraint, and fix up 
    -- the view. (Which might mean just including the new "trans_amount" 
    -- column, or might mean dropping the view altogether.) 
    trans_amount money not null, 

    -- Only (b)uys always result in a negative amount. 
    check ( 
    trans_amount = (case when action = 'b' then qty * price * (-1) 
         else     qty * price 
        end) 
), 

    -- (d)eposits always have a quantity of 1. Simple, makes logical 
    -- sense, avoids NULL and avoids additional tables. 
    check ( 
    qty = (case when action = 'd' then 1 end) 
) 
); 

insert into stock_transactions values 
(1, current_timestamp, 1, 's', 30, 1.00, 30.00), 
(2, current_timestamp, 2, 'b', 30, 1.00, -30.00), 
(3, current_timestamp, 1, 's', 20, 2.00, 40.00), 
(4, current_timestamp, 3, 'b', 20, 2.00, -40.00), 
(5, current_timestamp, 3, 'd', 1, 100.00, 100.00); 

但是看看發生了什麼。現在我們已經將存款添加爲一種交易類型,這不再是股票交易的表格。現在它更像是一個賬戶交易表。

您需要的不僅僅是一個CHECK約束,以確保一個帳戶有足夠的餘額來購買帳戶持有者想要購買的任何東西。

在SQL Server中,有關聚簇索引的決定很重要。給一些思考和測試。我希望你經常查詢帳戶ID號碼。