过滤的唯一约束或类似工具

时间:2016-09-23 08:22:16

标签: sql sql-server sql-server-2008 tsql

我需要弄清楚一个设计错误的解决方法,现在修复已经太晚了。我基本上希望重复的数据进入一个特定结构的表来避免它:

CREATE TABLE building (
    building_id INT IDENTITY(1, 1) NOT NULL,
    address_id INT NOT NULL,
    company_id INT NOT NULL,
    CONSTRAINT building_pk PRIMARY KEY (building_id),
    CONSTRAINT building_fk1 FOREIGN KEY (address_id) REFERENCES address (address_id),
    CONSTRAINT building_fk2 FOREIGN KEY (company_id) REFERENCES company (company_id)
);
CREATE INDEX building_idx1 ON building (address_id);
CREATE INDEX building_idx2 ON building (company_id);

/* Prevent dupes */
ALTER TABLE building ADD CONSTRAINT building_uk1 UNIQUE (address_id);

(原始本地化名称已更改,以使其更清晰且与问题相关。)

Acme Inc.的 export buildings API将发送共享相同地址的不同建筑物。删除building_uk1会破坏某些假设唯一性的功能,此时我们无法承担重大的重写。

我想评估仅针对上述公司(building_uk1)禁用company_id=314的效果,这可能没有依赖于唯一性的功能。我有哪些选择放松building_uk1并仅在company_id不是314时强制执行?

2 个答案:

答案 0 :(得分:6)

一个简单的唯一filtered index就足够了:

CREATE UNIQUE NONCLUSTERED INDEX [IX_building_uk1] ON [dbo].[building]
(
    [address_id] ASC
)
WHERE (company_id <> 314)

答案 1 :(得分:0)

你可以通过检查收集来实现这一点,让我看看我是否理解你的要求正确

创建一个函数,如果它不是building_id 314那么将检查它是否

CREATE FUNCTION CheckDistinctConstraint ()
RETURNS int
AS
BEGIN
  DECLARE @retValue int = 0
  DECLARE @cnt int = 0
  DECLARE @distcnt int = 0
  SELECT
    @cnt = COUNT(*),
    @distcnt = COUNT(DISTINCT address_id)
  FROM building
  WHERE company_id <> 314
  IF @cnt <> @distcnt
  BEGIN
    SET @retValue = 1
  END
  RETURN @retValue
END

通过应用此功能添加约束

ALTER TABLE dbo.Building
  ADD CONSTRAINT CheckDistConstraint CHECK (dbo.CheckDistinctConstraint() =0);

创建表脚本

CREATE TABLE building (
    building_id INT  NOT NULL,
    address_id INT NOT NULL,
    company_id INT NOT NULL--,
    CONSTRAINT building_pk PRIMARY KEY (building_id)--,
    --CONSTRAINT building_fk1 FOREIGN KEY (address_id) REFERENCES address (address_id),
    --CONSTRAINT building_fk2 FOREIGN KEY (company_id) REFERENCES company (company_id)
);

--inserts successfully
insert into building ( building_id, address_id, company_id) values
(1,11,22)

--insert failed bcos check constraint
insert into building ( building_id, address_id, company_id) values
(5,11,315)

-- insert successfull eventhough duplicate in address_id but building_id is 314
insert into building ( building_id, address_id, company_id) values
(311,11,314)

不确定你是否看起来像这样?