跨表的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

我该如何解决这种情况?

基本上,两者的代码都Brand/Product不能在公司内重复。

笔记:

我得到的错误是:

消息10116,级别16,状态1,行3无法在视图“ XXXX.dbo.TestView”上创建索引,因为它包含一个或多个UNION,INTERSECT或EXCEPT运算符。考虑为每个查询创建一个单独的索引视图,这是原始视图的UNION,INTERSECT或EXCEPT运算符的输入。

注2:

当我使用子查询时,出现以下错误:

消息10109,级别16,状态1,行3无法在视图“ XXXX.dbo.TestView”上创建索引,因为它引用了派生表“ a”(由FROM子句中的SELECT语句定义)。考虑删除对派生表的引用,或者不对视图建立索引。

**注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, 1, 'Brand 4', 400 ),
(5, 3, 'Brand 5', 500 )

INSERT INTO Product
(
    Id,
    BrandId,
    Name,
    Code
)
VALUES
(1001, 1, 'Product 1001', 1 ),
(1002, 1, 'Product 1002', 2 ),
(1003, 3, 'Product 1003', 3 ),
(1004, 3, 'Product 1004', 301 ),
(1005, 4, 'Product 1005', 5 )

如果我们扩展结果,则期望是Brand Code + CompanyProduct Code + Company唯一。

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,
    CompanyId,
    Name,
    Code
)
VALUES 
(6, 1, 'Brand 6', 999)

INSERT INTO Product
(
    Id,
    BrandId,
    Name,
    Code
)
VALUES
(1006, 2, 'Product 1006', 999)

该产品属于其他公司,因此我们得到

Company / Brand|Product Code
1 / 999 <-- Brand
2 / 999 <-- Product

这是独一无二的。

但是,如果您有2个品牌和1个产品。

INSERT INTO Brand
(
    Id,
    CompanyId,
    Name,
    Code
)
VALUES 
(7, 1, 'Brand 7', 777)
(8, 1, 'Brand 8', 888)

INSERT INTO Product
(
    Id,
    BrandId,
    Name,
    Code
)
VALUES
(1007, 8, 'Product 1008', 777)

这会产生

Company / Brand|Product Code
1 / 777 <-- Brand
1 / 888 <-- Brand
1 / 777 <-- Product

这是不允许的。

希望有道理。

注4:

@spaghettidba的答案解决了跨表问题,第二个问题是Brand表本身中的重复项。

我设法通过在brand表上创建单独的索引来解决此问题:

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,
    Name varchar(50),
    Code int
)
GO

INSERT INTO Brand
(
    Id,
    CompanyId,
    Name,
    Code
)
VALUES (1, 1, 'Brand 1', 100 ),
(2, 2, 'Brand 2', 200 ),
(3, 3, 'Brand 3', 300 ),
(4, 1, 'Brand 4', 400 ),
(5, 3, 'Brand 5', 500 )



INSERT INTO Product
(
    Id,
    BrandId,
    Name,
    Code
)
VALUES
(1001, 1, 'Product 1001', 1 ),
(1002, 1, 'Product 1002', 2 ),
(1003, 3, 'Product 1003', 3 ),
(1004, 3, 'Product 1004', 301 ),
(1005, 4, 'Product 1005', 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, State 1, 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.

希望这可以帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

SQL Server跨表联接

来自分类Dev

sql server:唯一约束生成唯一键和唯一索引

来自分类Dev

sql server:唯一约束生成唯一键和唯一索引

来自分类Dev

sql server:唯一约束生成唯一键和唯一索引

来自分类Dev

SQL Server中主键和唯一索引之间的区别

来自分类Dev

SQL Server跨多个表联接

来自分类Dev

我的SQL Server表仅由3列组成,具有唯一索引。索引应该聚类吗?

来自分类Dev

SQL Server中的唯一键是聚集索引还是非聚集索引?

来自分类Dev

SQL Server是否在非聚集非唯一索引中索引空值?

来自分类Dev

跨多个表级别的SQL Server外键

来自分类Dev

跨 SQL Server 中的 3 个表进行透视查询

来自分类Dev

跨多个表的唯一 GUID

来自分类Dev

在SQL Server中创建具有唯一索引但没有主键的表有什么影响?

来自分类Dev

使用触发器在 SQL Server 中具有复杂条件的表上创建唯一的过滤索引

来自分类Dev

如何使用SQL Server管理对象(SMO)对包含的列编写唯一索引的脚本?

来自分类Dev

SQL Server唯一索引(所有)NON-NULL行值

来自分类Dev

非唯一列上的SQL Server聚集索引

来自分类Dev

如何在 SQL Server 上创建唯一的 MD5 哈希索引?

来自分类Dev

MySQL朋友表双向唯一索引

来自分类Dev

SQL Server:表名唯一性

来自分类Dev

SQL Server:查找跨数据库的唯一表列表

来自分类Dev

SQL:添加唯一索引和添加唯一索引之间的区别?

来自分类Dev

跨表的Postgres唯一组合约束

来自分类Dev

跨Microsoft Server Management Studio中两个不同表的SQL更新

来自分类Dev

插入表或更新是否存在多个唯一索引(MySQL)

来自分类Dev

SQLServer 2012:表创建期间的非唯一索引定义?

来自分类Dev

SQL:跨多个表联接对一个范围进行分组,返回包括0在内的计数

来自分类Dev

SQL:跨多个表联接对一个范围进行分组,返回包括0在内的计数

来自分类Dev

sql server选择ID唯一

Related 相关文章

  1. 1

    SQL Server跨表联接

  2. 2

    sql server:唯一约束生成唯一键和唯一索引

  3. 3

    sql server:唯一约束生成唯一键和唯一索引

  4. 4

    sql server:唯一约束生成唯一键和唯一索引

  5. 5

    SQL Server中主键和唯一索引之间的区别

  6. 6

    SQL Server跨多个表联接

  7. 7

    我的SQL Server表仅由3列组成,具有唯一索引。索引应该聚类吗?

  8. 8

    SQL Server中的唯一键是聚集索引还是非聚集索引?

  9. 9

    SQL Server是否在非聚集非唯一索引中索引空值?

  10. 10

    跨多个表级别的SQL Server外键

  11. 11

    跨 SQL Server 中的 3 个表进行透视查询

  12. 12

    跨多个表的唯一 GUID

  13. 13

    在SQL Server中创建具有唯一索引但没有主键的表有什么影响?

  14. 14

    使用触发器在 SQL Server 中具有复杂条件的表上创建唯一的过滤索引

  15. 15

    如何使用SQL Server管理对象(SMO)对包含的列编写唯一索引的脚本?

  16. 16

    SQL Server唯一索引(所有)NON-NULL行值

  17. 17

    非唯一列上的SQL Server聚集索引

  18. 18

    如何在 SQL Server 上创建唯一的 MD5 哈希索引?

  19. 19

    MySQL朋友表双向唯一索引

  20. 20

    SQL Server:表名唯一性

  21. 21

    SQL Server:查找跨数据库的唯一表列表

  22. 22

    SQL:添加唯一索引和添加唯一索引之间的区别?

  23. 23

    跨表的Postgres唯一组合约束

  24. 24

    跨Microsoft Server Management Studio中两个不同表的SQL更新

  25. 25

    插入表或更新是否存在多个唯一索引(MySQL)

  26. 26

    SQLServer 2012:表创建期间的非唯一索引定义?

  27. 27

    SQL:跨多个表联接对一个范围进行分组,返回包括0在内的计数

  28. 28

    SQL:跨多个表联接对一个范围进行分组,返回包括0在内的计数

  29. 29

    sql server选择ID唯一

热门标签

归档