创建索引视图时如何引用表两次?如果没有它,我可以基于 2 个表和多行强制执行唯一性吗?

2023-12-31

EDIT:添加了我试图禁止的示例数据。

这个问题类似于:无法在视图上创建聚集索引,因为我两次引用同一个表,有什么解决方法吗? https://stackoverflow.com/questions/1011595/cannot-create-a-clustered-index-on-a-view-because-im-referencing-the-same-table但那里的答案对我没有帮助。我正在努力加强独特性,因此如果没有其他选择,“不要这样做”的答案并不能帮助我取得进步。

问题示例(简化):

CREATE TABLE [dbo].[Object]
(
   Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
   OrgId UNIQUEIDENTIFIER
)

CREATE TABLE [dbo].[Attribute]
(
   Id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
   Name NVARCHAR(256) NOT NULL
)

CREATE TABLE [dbo].[ObjectAttribute]
(
   Id INT NOT NULL IDENTITY(1, 1),
   ObjectId INT NOT NULL,
   AttributeId INT NOT NULL,
   Value NVARCHAR(MAX) NOT NULL,

   CONSTRAINT FK_ObjectAttribute_Object FOREIGN KEY (ObjectId) REFERENCES [Object] (Id),
   CONSTRAINT FK_ObjectAttribute_Attribute FOREIGN KEY (AttributeId) REFERENCES Attribute (Id)
)
GO

CREATE UNIQUE INDEX IUX_ObjectAttribute ON [dbo].[ObjectAttribute] ([ObjectId], [AttributeId])
GO

CREATE VIEW vObject_Uniqueness
WITH SCHEMABINDING
AS
SELECT
    ObjectBase.OrgId
    , CAST(OwnerValue.Value AS NVARCHAR(256)) AS OwnerValue
    , CAST(NameValue.Value AS NVARCHAR(50)) AS NameValue
FROM [dbo].[Object] ObjectBase
INNER JOIN [dbo].ObjectAttribute OwnerValue
    INNER JOIN [dbo].Attribute OwnerAttribute
        ON OwnerAttribute.Id = OwnerValue.AttributeId
        AND OwnerAttribute.Name = 'Owner'
    ON OwnerValue.ObjectId = ObjectBase.Id
INNER JOIN [dbo].ObjectAttribute NameValue
    INNER JOIN [dbo].Attribute NameAttribute
        ON NameAttribute.Id = NameValue.AttributeId
        AND NameAttribute.Name = 'Name'
    ON NameValue.ObjectId = ObjectBase.Id
GO

/*
Cannot create index on view "[Database].dbo.vObject_Uniqueness". The view contains a self join on "[Database].dbo.ObjectAttribute".
*/
CREATE UNIQUE CLUSTERED INDEX IUX_vObject_Uniqueness
ON vObject_Uniqueness (OrgId, OwnerValue, NameValue)
GO

DECLARE @Org1 UNIQUEIDENTIFIER = NEWID();
DECLARE @Org2 UNIQUEIDENTIFIER = NEWID();

INSERT [dbo].[Object]
(
    OrgId
)
VALUES
    (@Org1) -- Id: 1
    , (@Org2) -- Id: 2
    , (@Org1) -- Id: 3

INSERT [dbo].[Attribute]
(
    Name
)
VALUES
    ('Owner') -- Id: 1
    , ('Name') -- Id: 2
    --, ('Others')

-- Acceptable data.
INSERT [dbo].[ObjectAttribute]
(
    AttributeId
    , ObjectId
    , Value
)
VALUES
    (1, 1, 'Jeremy Pridemore') -- Owner for object 1 (Org1).
    , (2, 1, 'Apple') -- Name for object 1 (Org1).
    , (1, 2, 'John Doe') -- Owner for object 2 (Org2).
    , (2, 2, 'Pear') -- Name for object 2 (Org2).

-- Unacceptable data.
-- Org1 already has an abject with an owner value of 'Jeremy' and a name of 'Apple'
INSERT [dbo].[ObjectAttribute]
(
    AttributeId
    , ObjectId
    , Value
)
VALUES
    (1, 3, 'Jeremy Pridemore') -- Owner for object 3 (Org1).
    , (2, 3, 'Apple') -- Name for object 3 (Org1).

-- This is the bad data. I want to disallow this.
SELECT
    OrgId, OwnerValue, NameValue
FROM vObject_Uniqueness
GROUP BY OrgId, OwnerValue, NameValue
HAVING COUNT(*) > 1

DROP VIEW vObject_Uniqueness
DROP TABLE ObjectAttribute
DROP TABLE Attribute
DROP TABLE [Object]

此示例将产生错误:

Msg 1947, Level 16, State 1, Line 2 Cannot create index on view "TestDb.dbo.vObject_Uniqueness". The view contains a self join on "TestDb.dbo.ObjectAttribute".

如图所示,我使用带有 2 个表的属性系统来表示一个对象及其值。对象的存在以及对象上的 OrgId 位于主表中,其余值是辅助表中的属性。

首先,我不明白为什么这说有一个自连接。我加入来自Object to ObjectAttribute两次。不知道我要从哪一张桌子转到同一张桌子ON clause.

其次,有没有办法让这项工作发挥作用?或者如何增强我在这里追求的独特性?我想要的最终结果是,通过Object.OrgId,我没有两个Object有的行ObjectAttribute引用它们的记录提供相同的“所有者”和“名称”值。因此,对于任何给定的 OrgId、Owner 和 Name 值都必须是唯一的Object.


我认为你可以为此创建辅助表:

CREATE TABLE [dbo].[ObjectAttributePivot]
(
   Id int primary key,
   OwnerValue  nvarchar(256),
   NameValue nvarchar(50)
)
GO

然后创建辅助触发器以保持数据同步:

create view vw_ObjectAttributePivot
as
    select
        o.Id,
        cast(ov.Value as nvarchar(256)) as OwnerValue,
        cast(nv.Value as nvarchar(50)) as NameValue
    from dbo.Object as o
        inner join dbo.ObjectAttribute as ov on ov.ObjectId = o.Id
        inner join dbo.Attribute as ova on ova.Id = ov.AttributeId and ova.Name = 'Owner'
        inner join dbo.ObjectAttribute as nv on nv.ObjectId = o.Id
        inner join dbo.Attribute as nva on nva.Id = nv.AttributeId and nva.Name = 'Name'
GO

create trigger utr_ObjectAttribute on ObjectAttribute
after update, delete, insert
as
begin
    declare @temp_objects table (Id int primary key)

    insert into @temp_objects
    select distinct ObjectId from inserted
    union
    select distinct ObjectId from deleted

    update ObjectAttributePivot set
        OwnerValue = vo.OwnerValue,
        NameValue = vo.NameValue
    from ObjectAttributePivot as o
        inner join vw_ObjectAttributePivot as vo on vo.Id = o.Id
    where
        o.Id in (select t.Id from @temp_objects as t)

    insert into ObjectAttributePivot (Id, OwnerValue, NameValue)
    select vo.Id, vo.OwnerValue, vo.NameValue
    from vw_ObjectAttributePivot as vo
    where
        vo.Id in (select t.Id from @temp_objects as t) and
        vo.Id not in (select t.Id from ObjectAttributePivot as t)

    delete ObjectAttributePivot
    from ObjectAttributePivot as o
    where
        o.Id in (select t.Id from @temp_objects as t) and
        o.Id not in (select t.Id from vw_ObjectAttributePivot as t)
end
GO

之后,您可以创建独特的视图:

create view vObject_Uniqueness
with schemabinding
as
    select
        o.OrgId,
        oap.OwnerValue,
        oap.NameValue
    from dbo.ObjectAttributePivot as oap
        inner join dbo.Object as o on o.Id = oap.Id
GO

CREATE UNIQUE CLUSTERED INDEX IUX_vObject_Uniqueness
ON vObject_Uniqueness (OrgId, OwnerValue, NameValue)
GO

sql fiddle demo http://sqlfiddle.com/#!3/59dc3/3

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建索引视图时如何引用表两次?如果没有它,我可以基于 2 个表和多行强制执行唯一性吗? 的相关文章

  • 当嵌入式键包含 SQL Server 上的标识列时,Hibernate 插入失败

    我正在尝试使用 hibernate 映射实体 但是使用 SQL Server 我无法继续 以下是详细信息 SQL Server 实体 CREATE TABLE dbo BOOK EMBEDDED row id bigint IDENTITY
  • 更改 SQL Server 中的身份种子(永久!)

    有没有办法永久更改身份列的身份种子 使用 DBCC CHECKIDENT 似乎只是设置了最后一个值 如果表被截断 所有值都会重置 dbcc checkident Test SeedIdent reseed 1000 select name
  • CDC 已启用,但未填充 cdc.dbo_CT 表

    我已使用以下步骤启用 CDC exec sys sp cdc enable db exec sys sp cdc enable table source schema N dbo source name N table name role
  • 对不同记录进行 PIVOT 查询

    我有下表 Id Code percentage name name1 activity 1 Prashant 43 43 James James Running 1 Prashant 70 43 Sam Sam Cooking 1 Pras
  • 如何从代码获取复制状态

    我已经在 SQL Server 2005 数据库上完成了复制 现在我想从我的 GUI 显示状态 可以是 C 或其他 是否有任何方法或 API 可以让我监控复制状态 这是为了客户端确认复制正在工作 Thanks 像这样的事情 http www
  • 触发器定义中的 DELETE 语句问题

    我创建了一个插入 更新触发器 旨在根据插入的数据更新不同表中的信息 触发器执行 或应该执行 的最后一件事是从目标表中删除所有数据 这些数据的条件在触发器的插入部分期间可能已更改 除了最后的之外 一切似乎都在触发DELETE陈述 它正在执行D
  • 查找每个客户组的最新帐户

    我有一个包含客户信息的表 每个客户都会分配一个客户 ID 他们的 SSN 他们在开设更多帐户时会保留该 ID 两个客户可能使用同一个帐户 每个客户都有自己的 ID 帐号不按日期排序 我想找到每个客户或客户组的最新帐户 如果两个客户曾经一起使
  • 插入 SQL Server 视图时使用 @@identity 或输出?

    请原谅我 我对 StackOverflow 和 SQL 都是新手 Tl dr 使用时 identity 或任何其他选项 例如scope identity或输出变量 是否也可以使用视图 这是一个使用存储过程的示例 identity SNIP
  • SQL Case 语句会失败吗?

    有没有办法让 SQL 中的 CASE 语句像 C 中的 case 语句一样失败 我不想做的是下面的例子 但如果这是我唯一的选择 我想我会选择它 EXAMPLE NewValue CASE WHEN MyValue 1 THEN CAST M
  • 我应该在删除数据之前禁用聚集索引吗?

    我知道这已经像任何事情一样被讨论过 但找不到我可以接受的可靠答案 假设我有一个有100亿条记录的表 需要删除where子句中带有标识列的记录 我应该选择哪个选项 选项1 禁用索引 这将节省删除后重新排列索引的开销 但会花费更长的时间来搜索需
  • 将记录与另一个表上的最新记录连接

    我正在尝试创建一个 SQL 视图 我如何从一个表中选择最新的记录 而其他记录保持原样 我需要从所有表中选择所有记录 这工作正常 但我需要仅按日期选择最新的提案 这是我遇到的问题 这是我到目前为止所拥有的 SELECT TOP 100 PER
  • 仅选择一半记录

    我试图弄清楚如何选择 ID 为空的一半记录 我想要一半 因为我将使用该结果集来更新另一个 ID 字段 然后我将使用该 ID 字段的另一个值更新其余部分 所以本质上我想用一个数字更新一半记录 someFieldID 用另一个数字更新其余记录
  • 在 SQL Server 2014 中使用带有事务的存储过程的 TransactionScope

    我正在使用 C 和 ADO NetTransactionScope在 ASP Net 应用程序中运行事务 该事务应该在多个表中保存一些数据 然后向订阅者发送电子邮件 Question 是否有效使用TransactionScope 当它包含对
  • 如何在 Windows 7 - 64 位中安装 IBM db2 ODBC 驱动程序?

    我需要从本地 SQL Server 2008 R2 连接到远程 DB2 我不想使用链接服务器 因此 我正在搜索下载并尝试安装 IBM DB2 驱动程序 因为主机集成服务器附带的用于 DB2 的 Microsoft ODBC 驱动程序非常昂贵
  • SQL Server 数据归档解决方案

    我正在寻找一种解决方案来存档数据库中存在的数据 我的数据库是 SQL Server 2008 大约有 250 个表 我搜索网络并找到以下链接 http www dbazine com sql sql articles charran13 h
  • 删除 MongoDB 查询结果中的 "scanAndOrder" : true

    所以我的数据库中有一个带有以下分片键的集合 cl yyyy mm user id N 当我执行以下查询时 db collection find cl 2012 03 user id in users id lt new ObjectId 4
  • 为什么实体框架 6 在插入后不只选择scope_identity()?

    当您使用 EF 6 1 保存实体时 将生成并执行以下 SQL 代码 exec sp executesql N INSERT dbo Customers Name FirstName VALUES 0 1 SELECT CustomerId
  • 如何在 SQL 中编写 where 子句来按一天中的时间过滤 DATETIME 列?

    我有带有 DATETIME 列时间戳的数据 我想将其过滤到 DATETIME 介于上午 9 30 到下午 5 30 之间的任意一天的记录集 最好的方法是什么 更新 更改是因为我需要精确到分钟 而不仅仅是小时 对于那个很抱歉 您始终可以将其编
  • 无法在 SSIS 查找中选择 ODBC 源

    我正在创建一个用于更新 SQL Server 中的表的包 要更新的详细信息是从 MySQL 数据库获取的 为此 我使用 ODBC 连接管理器连接到 MySQL 但此 ODBC 连接管理器未在 OLE DB 连接管理器中列出 我可以在 Too
  • 获取SQL中前2个特殊字符之间的字符

    我有数据在sql 只是要注意 SQL STudio is the IDE like data a 10 b c a 1 b c 我想获取前两个符号之间的数据 Output 10 1 这就是我的方法 SELECT CAST

随机推荐

  • 方法参数的编译时验证

    我在这里发现了一些类似的问题 但不完整的答案没有帮助 而且比澄清任何事情都产生了更多的混乱 所以我尝试给出一个更结构化的问题 并希望得到能够帮助更多用户的答案 我的简化示例 我有一个带有两个不同构造函数的 Java 类 public cla
  • 从目录中读取所有文本文件

    我是 python 新手 我使用以下代码来提取输出作为情感分析 import json from watson developer cloud import ToneAnalyzerV3Beta import urllib request
  • Android Studio - 错误:程序类型已存在

    当我尝试编译代码时 Android Studio 3 0 1 上出现以下错误 Error Program type already present com squareup picasso Action RequestWeakReferen
  • BasicDatasource 和 PoolingDatasource 之间的区别

    org apache commons dbcp BasicDatasource 和 PoolingDataSoure 之间有什么区别 两者都支持连接池吗 何时使用它们中的每一个 基本数据源是 作为javadoc http commons a
  • Mustache 在服务器 (rails) 和客户端 (javascript) 上渲染

    是否有关于在服务器 使用 Rails 和客户端 使用 javascript 上使用 Mustache 最佳实践的文档 hello world mustache Hello planet some other file
  • C# - 按块上传文件 - 最后一个块大小错误

    我正在尝试将大文件分块上传到第三部分服务 但我对最后一块有问题 最后一个块总是小于 5mb 但所有块都包括 最后一个大小相同 5mb 我的代码 int chunkSize 1024 1024 5 using Stream streamx n
  • PowerShell:如何获得正确的 if else 构造?

    我正在尝试学习 powershell 并尝试构建一个 if else 语句 if Get Process Select Object name eq svchost Write Host seen else Write Host not s
  • Facebook 机器人分析事件记录

    我目前正在开发一个消息机器人 并尝试使用 Facebook 的应用程序分析平台记录其他事件 相关文件 消息机器人的事件 https developers facebook com docs app events bots for messe
  • 如何使用 PHPUnit 测试远程 Postgres 服务器上的数据库交互?

    我正在尝试对我创建的类进行单元测试 但大多数类都处理数据库 我已经在本地测试了非数据库相关的类 但当涉及到使用数据库时 尤其是远程数据库 我感到很困惑 该指南显示使用 PDO 访问本地数据库 该数据库似乎转储到 XML 文件 因此它对我来说
  • 找到颜色范围内最接近的颜色匹配[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有十个十六进制 RGB 颜色值 它们是肤色 我希望能够找到与特定十六进制 RGB 值最接近的匹配 我会以某种方式从起始颜色迭代直到落
  • android Recyclerview Layoutmanager的onLayoutChildren在item内容更改时调用

    我有一个带有自定义布局管理器的回收器视图 它是一个twowayview staggeredgridview布局管理器https github com lucasr twoway view blob master layouts src ma
  • 禁止 XmlSerializer 发出空值类型

    请考虑以下 Amount 值类型属性 该属性被标记为可为 null 的 XmlElement XmlElement IsNullable true public double Amount get set 当可为 null 的值类型设置为
  • 实例变量定义和实例块

    我有以下代码 s Hello String s 这编译得很好 这意味着变量定义在实例块之前执行 但是 如果我使用以下代码 它不会编译 错误 非法前向引用 s Hello String ss s String s 因此 不可能在变量之前的实例
  • setwd() 在当前工作目录中

    我有一个文件夹列表 每个文件夹中都有一个与 R 相同的脚本 必须在文件夹中的文件上运行 我编写了一次脚本并将脚本复制到每个文件夹中 问题是我有大约 100 个文件夹的列表 因此我不可能手动在当前工作目录中 setwd 我想知道是否可以设置当
  • Arm GCC 链接器:如何将数据放在 (rw) 非易失性存储器中的绝对地址处

    我面临以下问题 我正在对 ARM cortex M4 微控制器进行编程 我希望它具有 IP 地址 网络掩码 网关等的默认值 该默认值应该可以通过串行通信进行更改 并且更改应该是持久的 例如 IP 地址和网络掩码的默认值为 192 168 1
  • AngularJS 按下按键时更改多行选择 ng-grid 属性

    我在视图中定义了以下网格 div class gridStyle hide div 我想仅在按下 ctrl 键时才允许多重选择 所以我在控制器中将 multiSelect 属性定义为 false scope resultsOptions d
  • mailto:带附件的链接

    我为我的客户制作了一个应用程序 它提供具有以下示例结构的 zip 文件 index html files file pdf inc style css 基本上 用户将使用名为 Sites 2 Go 的应用程序将 zip 文件传输到他们的 i
  • SQL Server 中什么被视为“大”表?

    我有一个表 其中有 1000 万条记录 这算是很多记录吗 我应该担心搜索时间吗 如果没有 它会继续增长 那又怎样is算一张大桌子吗 表大小对搜索时间的影响有多大 我可以采取哪些措施来改善这些问题 最好是在它们成为问题之前 大 就像 聪明 它
  • v8旧空间和新空间是什么?

    Node js据我所知 有两个参数来控制内存分配 max new space size and max old space size 提到的具体是什么NEW SPACE and OLD SPACE things 在分代垃圾收集器 V8 使用
  • 创建索引视图时如何引用表两次?如果没有它,我可以基于 2 个表和多行强制执行唯一性吗?

    EDIT 添加了我试图禁止的示例数据 这个问题类似于 无法在视图上创建聚集索引 因为我两次引用同一个表 有什么解决方法吗 https stackoverflow com questions 1011595 cannot create a c