对于MS SQL列,等效的C#'readonly'?

时间:2011-08-02 14:50:16

标签: sql sql-server sql-server-2008 default-value alter-table

想象一下Price表格中有一个Products列,价格可能会发生变化。
我对它的改动很好但是我想将原始的Price值存储在另一列中。

MS SQL服务器可以自动执行此操作吗?

我可以使用默认值字段执行此操作吗?
 我必须申报一个触发器吗?

更新

我尝试使用Price来简化问题,但看起来这样会激起“使用单独表格”类型的答案。
对于我造成的困惑,我感到很遗憾。

在现实世界中,我需要存储一个外键ID,我是100%我只需要当前原始

更新2

我对所提出的不同方法感到有些困惑,所以请让我再次解释一下情况。

虚构Products表有三个字段:IDPriceOriginalPrice
我想在任何插入上设置OriginalPricePrice值。

有时它是从代码创建的单个产品。有时候,存储过程中有一千个由insert创建的产品,所以我也想正确处理这些产品。

设置OriginalPrice后,我从不打算更新它。

希望我的问题现在更清楚了 谢谢你的努力。

最终更新

我要感谢所有人,特别是@gbn,感谢他们的帮助 虽然我发布了my own answer,但它主要基于@gbn's answer以及他的进一步建议。他的答案也更完整,因此我将其标记为正确。

4 个答案:

答案 0 :(得分:3)

更新后,我们假设您只有旧值和新值。

如果由于客户端代码错误导致相同的更新快速连续发生并且您对历史不感兴趣(其他答案),请忽略

您可以使用触发器或存储过程。

就个人而言,我会使用存储过程来提供基本的控制。然后不需要直接的UPDATE权限,这意味着除非通过您的代码,否则只读

  CREATE PROC etc
  ...
  UPDATE
    MyTable
  SET
    OldPrice = Price,
    Price = @NewPrice,
    UpdatedBy = (variable or default)
    UpdatedWhen = DEFAULT --you have a DEFAULT right?
  WHERE
    PKCol = @SomeID
    AND --provide some modicum of logic to trap useless updates
    Price <> @NewPrice;

触发器类似,但您需要与INSERTED和DELETED表进行JOIN 如果有人直接更新OldPrice怎么办?

  UPDATE
    T
  SET
    OldPrice = D.Price
  FROM
    Mytable T
    JOIN
    INSERTED I ON T.PKCol = I.PKCol
    JOIN
    DELETED D ON T.PKCol = D.PKCol
  WHERE
    T.Price <> I.Price;

现在你明白为什么你会跳起来......?

问题编辑后,仅 INSERT

  UPDATE
    T
  SET
    OriginalPrice = I.Price
  FROM
    Mytable T
    JOIN
    INSERTED I ON T.PKCol = I.PKCol

但是如果所有INSERT都是通过存储过程发生的话我会把它设置在那里......

答案 1 :(得分:2)

SQL Server表列没有readonly属性。但是您可以使用触发器(和限制权限)来实现您描述的功能

外,它不是解决问题的最佳方法。而是将价格视为类型2 'slowly changing dimension'.这涉及具有'ValidTo'列(os'StartDate'和'EndDate'列),并关闭记录:

Supplier_Key    Supplier_Code   Supplier_Name   Supplier_State  Start_Date  End_Date
123           ABC             Acme Supply Co    CA            01-Jan-2000   21-Dec-2004
124           ABC             Acme Supply Co    IL            22-Dec-2004   

如果您确实使用了触发器的路径(我建议您使用SCD类型2),请确保它可以处理多行:Multirow Considerations for DML Triggers

答案 2 :(得分:1)

我建议您将价格存储在名为Prices的单独表格中,其中包含PriceDate列。

然后,只要价格更新,INSERT就会有Prices表中的新记录。然后当你需要知道当前的价格时,你可以从那里开始。


但是,如果您希望自动更新OriginalPrice列,可以在表格中添加TRIGGER来执行此操作:

http://msdn.microsoft.com/en-us/library/aa258254%28v=sql.80%29.aspx

答案 3 :(得分:0)

这是我最终得到的结果,得到了@gbn@Mitch@Curt的大力帮助:

create trigger TRG_Products_Price_I --common-ish naming style
    on dbo.Products after insert as
begin
    set nocount on

        update m
        set OriginalPrice = i.Price 
        from Products p
        join inserted i on p.ID = i.ID

end

我也试图关注this article 谢谢大家!