0

我特别需要一个名为ProductCode的计算列

ProductId | SellerId | ProductCode
1           1           000001
2           1           000002
3           2           000001       
4           1           000003

ProductId是身份,以 1 递增 。SellerId是外键。

所以我的计算列ProductCode必须查看卖家有多少产品,格式为 000000。这里的问题是如何知道要查找哪些卖家产品?

我写了一个 TSQL,它不看卖家有多少产品

ALTER TABLE dbo.Product
ADD ProductCode AS  RIGHT('000000' + CAST(ProductId AS VARCHAR(6)) , 6) PERSISTED
4

2 回答 2

2

您不能拥有基于正在更新的当前行之外的数据的计算列。您可以做的最好的事情是创建一个后触发器来查询整个表以查找产品代码的下一个值。但是为了完成这项工作,您必须使用排他表锁,这将彻底破坏并发性,所以这不是一个好主意。

我也不建议使用视图,因为每次阅读表格时它都必须计算 ProductCode。这也将是一个巨大的性能杀手。通过不将值保存在数据库中以使其不再被触摸,您的产品代码将受到虚假更改(例如可能删除错误输入且从未使用过的产品的情况)。

这是我推荐的。创建一个新表:

dbo.SellerProductCode

SellerID  LastProductCode
--------  ---------------
  1        3
  2        1

该表可靠地记录了每个卖家最后使用的产品代码。在INSERT您的Product表上,触发器将LastProductCode针对所有受影响SellerID的 s 适当地更新此表中的 ,然后Product使用适当的值更新表中所有新插入的行。它可能看起来像下面这样。

查看此触发器在 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)。

查看 Sql Fiddle以了解演示该技术的工作、测试代码。现在您拥有无需更改且可靠的真实产品代码。

于 2013-02-20T01:15:54.143 回答
0
于 2013-02-19T21:38:06.520 回答