根據當前正在更新的行以外的數據,您不能擁有計算列。您可以做的最好的做法是自動創建一個後觸發器,查詢整個表以查找產品代碼的下一個值。但爲了完成這項工作,你必須使用獨佔表鎖,這將完全破壞併發性,所以這不是一個好主意。
我也不建議使用視圖,因爲每次讀取表時都必須計算ProductCode。這也是一個巨大的性能殺手。通過不再將數據保存在數據庫中,永遠不會再次觸及,您的產品代碼將受到虛假更改(例如可能會刪除錯誤輸入和未使用的產品)。
這是我推薦的。創建一個新表格:
dbo。SellerProductCode
SellerID LastProductCode
-------- ---------------
1 3
2 1
這臺可靠地記錄了每個賣家上次使用的產品代碼。在INSERT
到Product
表中,觸發器將適當地更新此表中LastProductCode
對所有受影響的SellerID
s,然後使用適當的值更新Product
表中的所有新插入的行。它可能看起來像下面那樣。
See this trigger working in a Sql Fiddle
CREATE TRIGGER TR_Product_I ON dbo.Product FOR INSERT
AS
SET NOCOUNT ON;
SET XACT_ABORT ON;
DECLARE @LastProductCode TABLE (
SellerID int NOT NULL PRIMARY KEY CLUSTERED,
LastProductCode int NOT NULL
);
WITH ItemCounts AS (
SELECT
I.SellerID,
ItemCount = Count(*)
FROM
Inserted I
GROUP BY
I.SellerID
)
MERGE dbo.SellerProductCode C
USING ItemCounts I
ON C.SellerID = I.SellerID
WHEN NOT MATCHED BY TARGET THEN
INSERT (SellerID, LastProductCode)
VALUES (I.SellerID, I.ItemCount)
WHEN MATCHED THEN
UPDATE SET C.LastProductCode = C.LastProductCode + I.ItemCount
OUTPUT
Inserted.SellerID,
Inserted.LastProductCode
INTO @LastProductCode;
WITH P AS (
SELECT
NewProductCode =
L.LastProductCode + 1
- Row_Number() OVER (PARTITION BY I.SellerID ORDER BY P.ProductID DESC),
P.*
FROM
Inserted I
INNER JOIN dbo.Product P
ON I.ProductID = P.ProductID
INNER JOIN @LastProductCode L
ON P.SellerID = L.SellerID
)
UPDATE P
SET P.ProductCode = Right('00000' + Convert(varchar(6), P.NewProductCode), 6);
請注意,即使插入多行這種觸發的工作。沒有必要預加載SellerProductCode
表格 - 新的賣家會自動添加。這將處理併發性問題。如果遇到併發問題,可以添加適當的鎖定提示而不會產生有害影響,因爲表格將保持非常小,並且可以使用ROWLOCK(除了需要範圍鎖定的INSERT)。
請做see the Sql Fiddle工作,測試代碼演示技術。現在您有real產品代碼,沒有任何理由可以更改並且可靠。
我會建議使用視圖來做這種計算。如果選擇性能是最重要的因素(我看你使用'persisted'),這個視圖甚至可以被索引。 – 2013-02-19 21:15:13
@TimLehner你能提供樣品嗎?我仍然想知道是否可以使用Computed列? – 2013-02-19 21:19:40