根据另一列

时间:2015-08-07 16:12:09

标签: sql-server

我有典型的Invoice / InvoiceItems主/详细信息表(每本书和教程都使用这些表作为示例)。我还有一个" Proforma"包含有时与发票有关的发票的数据的表格。两者都链接到发票中的每个项目,其中一列可选地引用形式表,如下所示:

id | id_invoice | id_proforma | amount ....... and a bunch of irrelevant stuff
-----------------------------------------------
1  | 1          | null        | 100
2  | 1          | null        | 40
3  | 2          | 3           | 1000
4  | 3          | 4           | 473
5  | 3          | 4           | 139

基本上,发票中的每个都可以链接到形式表。还有一个业务规则,即每个形式只能在一张发票中使用(在同一张发票中的许多项目中都可以使用它)。

目前该规则在应用程序端实施,但这存在并发问题,因为2个用户可以同时获取相同的形式,系统会让它通过。我的目的是让数据库在一些前端视觉线索之外对此进行验证,但到目前为止,我还没有为这种特殊情况提供方法。

过滤的唯一索引可以很好地发挥作用,除非相同的形式可以在同一发票中使用两次,所以我的问题是,如何让DB服务器强制执行该规则?

数据库引擎可以是SQL 2012或后者以及从快递到企业的任何版本。

1 个答案:

答案 0 :(得分:0)

您可以创建用户定义的标量函数,如果形式ID和发票ID组合有效,则返回TRUE。然后在表上放置一个检查约束,要求函数返回true。像这样(调整以适合您的表名称/需求):

-- Here's the function:
create function dbo.svfIsCombinationValid (
                                           @id_invoice  int
                                         , @id_proforma int
                                          )
returns bit
as
begin;

   declare @return bit = 1;

   if exists (
              select 1
                from dbo.YourInvoiceProformaXRefTable
               where id_proforma = @id_proforma
                 and id_invoice <> @id_invoice
             )
   begin;
      set @return = 0;
   end;

   return @return;

end;

之后,您可以更改表并添加检查约束:

alter table dbo.YourInvoiceProformaXRefTable
add constraint CK_YourInvoiceProformaXRefTable_UniqueInvoiceProforma
check (dbo.svfIsCombinationValid(id_invoice,id_proforma)=1);

这对于空值是可以的(多个id_invoice可以具有id_proforma NULL值)。但如果两个值都不为null,则组合必须为NEW或与现有行相同。