SQL Server唯一索引跨表
可以在表之间创建唯一的索引,基本上使用视图和唯一索引.
我有一个问题. 给定两(或三)表. Company - Id - Name Brand - Id - CompanyId - Name - Code Product - Id - BrandId - Name - Code 我想确保唯一性的组合: Company / Brand.Code 和 Company / Brand.Product/Code 是独一无二的 CREATE VIEW TestView WITH SCHEMABINDING AS SELECT b.CompanyId,b.Code FROM dbo.Brand b UNION ALL SELECT b.CompanyId,p.Code FROM dbo.Product p INNER JOIN dbo.Brand b ON p.BrandId = b.BrandId 创建视图是成功的. CREATE UNIQUE CLUSTERED INDEX UIX_UniquePrefixCode ON TestView(CompanyId,Code) 由于UNION而失败了 我如何解决这种情况? 品牌/产品的基本代码不能在公司内重复. 笔记: 我得到的错误是:
备注2: 当我使用子查询我得到以下错误:
**注3:** 所以给品牌: 从@ spaghettidba的答案. INSERT INTO Brand ( Id,CompanyId,Name,Code ) VALUES (1,1,'Brand 1',100 ),(2,2,'Brand 2',200 ),(3,3,'Brand 3',300 ),(4,'Brand 4',400 ),(5,'Brand 5',500 ) INSERT INTO Product ( Id,BrandId,Code ) VALUES (1001,'Product 1001',1 ),(1002,'Product 1002',2 ),(1003,'Product 1003',3 ),(1004,'Product 1004',301 ),(1005,4,'Product 1005',5 ) 期望的是,如果我们扩大结果,品牌代码公司或产品代码公司是独一无二的. Company / Brand|Product Code 1 / 100 <-- Brand 1 / 400 <-- Brand 1 / 1 <-- Product 1 / 2 <-- Product 1 / 5 <-- Product 2 / 200 <-- Brand 3 / 300 <-- Brand 3 / 500 <-- Brand 3 / 3 <-- Product 3 / 301 <-- Brand 没有重复.如果我们有一个具有相同代码的品牌和产品. INSERT INTO Brand ( Id,Code ) VALUES (6,'Brand 6',999) INSERT INTO Product ( Id,Code ) VALUES (1006,'Product 1006',999) 该产品属于不同的公司,所以我们得到 Company / Brand|Product Code 1 / 999 <-- Brand 2 / 999 <-- Product 这是独一无二的. 但如果你有2个品牌,和1个产品. INSERT INTO Brand ( Id,Code ) VALUES (7,'Brand 7',777) (8,'Brand 8',888) INSERT INTO Product ( Id,Code ) VALUES (1007,8,'Product 1008',777) 这会产生 Company / Brand|Product Code 1 / 777 <-- Brand 1 / 888 <-- Brand 1 / 777 <-- Product 这是不允许的. 希望是有道理的. 备注4: @ spaghettidba的答案解决了跨表问题,第二个问题在品牌表本身中重复. 我已经设法通过在品牌表上创建一个单独的索引来解决这个问题: CREATE UNIQUE NONCLUSTERED INDEX UIX_UniquePrefixCode23 ON Brand(CompanyId,Code) WHERE Code IS NOT NULL; 解决方法我在2011年发布了类似的解决方案.您可以在这里找到这篇文章:http://spaghettidba.com/2011/08/03/enforcing-complex-constraints-with-indexed-views/ 基本上,您必须创建一个包含正好两行的表,并且您将在CROSS JOIN中使用该表来复制违反业务规则的行. 在您的情况下,索引视图有点难以编码,因为您表达业务规则的方式.事实上,通过索引视图检查UNIONED表上的唯一性是不允许的,如您已经看到的. 然而,约束可以以不同的方式表达:由于companyId是由品牌隐含的,您可以避免使用UNION并简单地在产品和品牌之间使用JOIN,并通过在代码本身上添加JOIN谓词来检查唯一性. 你没有提供一些样本数据,我希望你不介意我会为你做的: CREATE TABLE Company ( Id int PRIMARY KEY,Name varchar(50) ) CREATE TABLE Brand ( Id int PRIMARY KEY,CompanyId int,Name varchar(50),Code int ) CREATE TABLE Product ( Id int PRIMARY KEY,BrandId int,Code int ) GO INSERT INTO Brand ( Id,Code ) VALUES (1,500 ) INSERT INTO Product ( Id,5 ) 据我所知,没有违反业务规则的行. 现在我们需要索引视图和两行表: CREATE TABLE tworows ( n int ) INSERT INTO tworows values (1),(2) GO 这是索引视图: CREATE VIEW TestView WITH SCHEMABINDING AS SELECT 1 AS one FROM dbo.Brand b INNER JOIN dbo.Product p ON p.BrandId = b.Id AND p.code = b.code CROSS JOIN dbo.tworows AS t GO CREATE UNIQUE CLUSTERED INDEX IX_TestView ON dbo.TestView(one) 此更新应该违反业务规则: UPDATE product SET code = 300 WHERE code = 301 其实你得到一个错误: Msg 2601,Level 14,Line 1 Cannot insert duplicate key row in object 'dbo.TestView' with unique index 'IX_TestView'. The duplicate key value is (1). The statement has been terminated. 希望这可以帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |