增加部分PK

时间:2013-01-23 23:28:33

标签: sql-server

我有一张桌子:

INSTRUCTIONS:
  RecipeID
  Step
  ...

RecipeID由另一个系统生成。 RecipeID不需要明确的外键关系。当我为特定配方插入Instructions步骤时,我希望Step增加。向新配方step添加步骤时应该返回0,如下所示:

RecipeID | Step
---------------
    0    |  0
    0    |  1

RecipeID | Step
---------------
    0    |  0
    0    |  1
    0    |  2

RecipeID | Step
---------------
    0    |  0
    0    |  1
    0    |  2
    1    |  0

我如何产生这种行为?

2 个答案:

答案 0 :(得分:2)

不要这样做 你自己的问题表明这是一个糟糕的主意。 你怎么能有部分钥匙? 根据定义,部分密钥不能是唯一的。

从步骤中你唯一需要的是一个订单,显示它们(或者用Row_number查询它们)为0到n是微不足道的。

考虑一下你必须做什么,插入你错过的一个步骤,或交换它们......

RecipeStepID(作为代理主键)

RecipeID,StepNumber作为索引

表的任何外键链接都使用代理键

然后重新订购只是搞乱了StepNo

从未见过你试图不会变成灾难的事情,我可以算一下,如果没有把我的连指手机关掉,它就没有开始作为一场灾难。

答案 1 :(得分:0)

免责声明:请参阅底部的说明。我不一定建议使用触发器。

您可以使用instead of触发器来更改将要插入的step的值:

Create Trigger Instructions_UpdateSet
  On [Instructions]
  Instead of Insert
AS
BEGIN
  insert instructions
  select
    i.recipe,
    coalesce(ii.maxstep, -1)
      + row_number() over (partition by i.recipe order by i.step),
    i.instruction
  from inserted i
  left join (select recipe, max(step) as maxstep from instructions group by recipe)
    ii on i.recipe = ii.recipe
END;

这应该无缝地处理单个或多个记录的插入。如果您在单个查询中插入多个记录,则可以提供step值以指示传入的插入记录的顺序,并且它们将被适当地排序并重新编号以在现有记录之后按顺序跟随。 / p>

演示:http://www.sqlfiddle.com/#!6/b13d5/1


在应用程序中使用触发器时需要注意的一些事项:

  • 很容易忘记触发因素,因为它们非常隐蔽。确保记录它们,否则当它们插入的数据在数据库中不相同时,下一个开发人员会感到困惑。
  • 如果您使用的是缓存层,请确保在插入记录后刷新缓存以获取触发器引起的更改。
  • 一般来说,我建议避免使用业务逻辑触发器。如果您正在寻找性能,那么最好使用存储过程,这对于意图和行为更为明显。触发器最适合透明操作,如数据验证,级联更新/删除,审计等。