标签: unique-constraint

如何强制确保与时间维度关联的唯一性?

我有一个数据库表AB,它跟踪AB随着时间的推移的关联:

create table AB columns (
   ARef ...,  -- FK of A
   BRef ...,  -- FK of B
   Since as Timestamp,
   Until as Timestamp,
   SomeAttrib1 ...,
   SomeAttrib2 ...
);
Run Code Online (Sandbox Code Playgroud)

我想声明一个唯一的键,以便相同的 A 和 B在相同的时间间隔内只能关联一次

我可以使用什么策略来表达这种约束?显然,仅进行 PK 是ARef,BRef,Since,Until不够的 - 这只会防止完全相同间隔的重复。我需要考虑一行的间隔如何与表中其他行的间隔重叠或不重叠。

要考虑的参数:

  • 我使用的是 SQL Server 2012,但我也很想知道其他 RDBMS 中有哪些可用的工具。
  • 虽然我意识到保留这个“历史”或“时间维度”可以被认为是对数据库的“分析”使用,但我不想要一个使用“维度”或“立方体”的解决方案......这是一个普通的需要为不同时间发生的关联分配不同属性的应用程序的事务数据库。
  • 我并没有特别关注时间戳……如果它们有帮助,我很乐意考虑“间隔”数据类型。

database-design datatypes unique-constraint

6
推荐指数
1
解决办法
2846
查看次数

在大表上“创建唯一索引”花费太长时间

我正在尝试恢复 GHTorrent 的数据库转储(包含 GitHub 元数据的 CSV 文件)。该commits表拥有超过 8.91 亿行,并且project_commits拥有超过 54 亿行。由于这些表相当大,我必须使用LOAD DATA INFILE外键检查来加载它们。我正在使用MyISAM引擎。将记录导入表后,我尝试为这些表创建索引。

我正在为表运行以下 mysql 命令commits,但它在超过 12 小时内才完成。

CREATE UNIQUE INDEX `sha` ON `ghtorrent_restore`.`commits` (`sha` ASC)  COMMENT '';
Run Code Online (Sandbox Code Playgroud)

提交表如下所示:

在此输入图像描述

my.cnf我已阅读有关缓慢索引的其他 stackexchange 问题,并在目录中的文件中设置以下内容/etc/mysql

[mysqld]
bulk_insert_buffer_size=1G
myisam_sort_buffer_size=8G
key_buffer_size=6G
sort_buffer_size=10M
Run Code Online (Sandbox Code Playgroud)

由于上一个命令没有及时完成,我不得不从控制台使用 ctrl+z 来停止它。我检查了 MySQL Workbench 上的表,它没有显示为损坏,但它显示索引长度约为 36GB。

在此输入图像描述

导入该表大约需要 25 分钟,因此我预计索引不会超过一个小时,但我现在运行“创建唯一索引”命令大约 2 小时,没有任何进展迹象。

当我运行该命令时,mysqld 占用大量 cpu 并且不断占用内存。达到 6GB 左右后,它变得不那么活跃,似乎几乎什么也不做。

在此输入图像描述

以下是该命令(在下图中选择的一个)在 mysql 工作台中的外观。

在此输入图像描述

我正在一台具有 16GB RAM 的 Linux Mint 17.03 机器上运行 Mysql …

mysql myisam index unique-constraint mysql-5.7

6
推荐指数
1
解决办法
5262
查看次数

DROP CONSTRAINT 后主键的索引会发生什么变化?

我正在运行 PostgreSQL 9.1.4。

我有一个包含许多现有行的表,以及一堆其他带有指向它的外键的表,我正在尝试:

1 - 删除当前主键上的 pkey 约束,因为它当前不是串行类型。

2 - 添加一个串行类型的列并将该新列作为主键。

3 - 将步骤 #1 的旧列设置为 UNIQUE 并为所有具有指向我的表的外键的表重新创建外键。事实上,这些表都有两个指向我的表的外键:一个指向当前作为主键的旧列,另一个指向新的串行类型列

我已经成功创建了一个执行此操作的脚本,但我想知道:

a) 在上面的第 1 步删除 pkey 约束是否也会删除与该主键关联的索引?

b)如果没有,有没有办法重用该索引?在第 3 步添加回 UNIQUE 约束后,会创建一个新索引还是使用之前存在的索引?除了创建的新列(串行主键)外,表中没有任何内容被更改。

编辑(一些澄清):

  • 我们将旧的 pk 列称为 OLD_PK,将 to-be-be-be-create-by-my-script 称为新的 pk 列 NEW_PK
  • OLD_PK 列的类型是 INT
  • OLD_PK 列不会也不能被删除(它的信息仍然有价值)因此它也不能将其自身转换为类型序列,现有数据必须保留。
  • 我知道串行是一种快捷方式。就像我说的,我已经想出了一个工作脚本,我和同事不确定的部分是索引以及从这个角度来看它是如何工作的。
  • 之前有一个指向 OLD_PK 的外键的所有表,在执行脚本后,将有一个指向 OLD_PK 的外键(比如“fkey_old_pk”)和另一个指向 NEW_PK 的外键(比如“fkey_new_pk”)

postgresql index database-design primary-key unique-constraint

5
推荐指数
1
解决办法
2094
查看次数

ALTER TABLE 中的 DROP/ADD UNIQUE 约束是原子的吗?

我有UNIQUE一个表上的多个字段的约束。我想更改此约束中的字段(删除一个字段)的图像。通常我会做这样的事情:

DROP INDEX unique_name ON table_name;
CREATE UNIQUE INDEX unique_name ON table_name (field1, field2, ...);
Run Code Online (Sandbox Code Playgroud)

但这是两个语句,在执行第一个语句后将UNIQUE不再有约束,因此任何INSERT可能都可能破坏约束,直到新的UNIQUE创建的。

还有另一种方法可以做到这一点:

ALTER TABLE table_name
DROP INDEX unique_name, 
ADD CONSTRAINT unique_name UNIQUE (field1, field2, ...);
Run Code Online (Sandbox Code Playgroud)

这是一种说法。问题是:这个语句会执行原子操作吗?我所说的原子是指完全没有约束的时候就没有时间窗口UNIQUE

mysql index alter-table unique-constraint

5
推荐指数
1
解决办法
6130
查看次数

为什么 MySQL 会标记不存在的重复键?

我正在auto-increment向大表中添加一个字段。

该字段已填充(大约 1-500M)并且新插入的内容正在正确地手动递增。为了验证,我运行了一个查询以显示任何重复项:

mysql> SELECT new_id, COUNT(*) AS count FROM my_table GROUP BY new_id HAVING count > 1;
#      No Results
Run Code Online (Sandbox Code Playgroud)

当我手动查看最新记录时,我会看到看起来像自动递增的BIGINT(20)字段。NULL该列中不存在 's 。

然而,当我尝试将索引更改为 a UNIQUE INDEX(从非唯一索引,但具有唯一值)时,它会触发DUPLICATE KEY错误。并且重复键始终为MAX(new_id)+1,因此有问题的重复项的aSELECT始终不返回任何结果。

这是我正在运行的内容:

mysql> SELECT MAX(new_id) FROM my_table;
+-------------+
| MAX(new_id) |
|   512345678 |
+-------------+
1 row in set (0.00 sec)

mysql> ALTER TABLE my_table
        DROP INDEX `idx_new_id`,
        ADD UNIQUE INDEX `idx_new_id ` USING BTREE (`new_id `); …
Run Code Online (Sandbox Code Playgroud)

mysql innodb duplication unique-constraint mysql-5.7

5
推荐指数
1
解决办法
3597
查看次数

SQL Server 2014 并发输入问题

在表中Orders,我存储了我们从所有商店收到的订单。由于一个订单可以有多个行,列中有OrderIDOrderLineID 在那里OrderID可以复制,但OrderLineID必须是一个顺序中是唯一的。

由于订单可以修改,存储过程首先检查收到的订单OrderLineID是否已经存在于表中,然后决定插入还是更新。为此,我们:

  • 从 XML 输入动态构建插入和更新语句
  • 插入客户表
  • 插入到 shippingAddresses 表中

然后是主表:

IF NOT EXISTS (Select 1 from Orders where OrderLineID=@OrderLineID ......)
INSERT INTO Orders () VALUES ()
ELSE UPDATE Orders SET ... WHERE OrderLineID=@OrderLineID
Run Code Online (Sandbox Code Playgroud)

或者该MERGE功能是否提供更好的性能/控制?

但问题如下:

由于线路问题/服务器繁忙等,Order消息(或修改)可能会被多次发送,我们不知道按哪个顺序发送。因此,为了避免Order修改后到达,从而覆盖修改,我们添加了一个时间列:

IF NOT EXISTS (Select 1 from Orders where OrderLineID=@OrderLineID)
INSERT INTO Orders () VALUES ()
ELSE UPDATE Orders SET ... WHERE OrderLineID=@OrderLineID AND LastModified<@CreatedTime
Run Code Online (Sandbox Code Playgroud)

这样,如果后一条消息比前一条消息旧,则对表没有影响。

但是,消息及其修改可能会在很短的时间内发送两次(或更多),以至于后一条消息在保存前一条消息之前到达。因此,对于存储过程的两次执行,它 …

sql-server concurrency unique-constraint

5
推荐指数
1
解决办法
1191
查看次数

有没有办法拥有唯一约束而不是唯一索引?

查看 Microsoft 文档,它说创建唯一约束时,会自动创建唯一索引。

是否有一个技巧/解决方法来拥有一个唯一的约束而不是一个唯一的索引,所以它不占用空间?

sql-server unique-constraint

5
推荐指数
1
解决办法
1111
查看次数

最小化/避免数据重复并在复合键和唯一索引之间进行选择

我对数据库开发完全陌生,我基本上正在尝试建立一个问题库。

问题必须根据类别、主题和主题进行分类。由于每个类可以有许多主题,并且每个主题可以在许多类中,因此我制作了一个名为 tb_SubjectClass 的连接表,其中主题和类是主键。

为了唯一标识任何章节,我需要主题和类的组合,因此我创建了 tb_Chapters,其中章节、主题和类作为主键,主题和类来自 tb_SubjectClass。然后我用 tb_Topics 重复了同样的事情,因为每个主题只能用主题、类和章节的组合来标识。

我把关系图放在下面。知道我期望在这个数据库中存储大约 50000 个问题(带有方程和图表)也可能是相关的。

数据库关系

主要问题:如果我决定坚持使用复合键/复合键,我的设计是否合适或可以进一步改进?

附带问题:在我的情况下,最好的方法是什么,考虑到以下因素:

  • 预计记录约 50000
  • 问题表 (tb_QnA) 将成为查询最多的表(用于选择和添加/删除数据)
  • 表 tb_Class、tb_Subjects 和 tb_SubjectClass 根本不会改变
  • 将数据库连接到 ac# winform 应用程序时易于编写查询(用于数据输入和生成报告)
  • 该项目将基于桌面

我主要一直都在数据库设计教程上tekstenuitleg.net和视频教程由WiseOwlTutorials。我最近也开始阅读Jan L. Harrington所著的Relational Database Design Clearly Explained一书。

database-design sql-server sql-server-2014 unique-constraint

5
推荐指数
1
解决办法
426
查看次数

对可为空的软删除标志设置唯一约束是否有意义?

所以我们目前有以下几点:

MYTABLE
COLUMN: ID (INTEGER Primary key, auto-incrementer)
COLUMN: START (DATE)
COLUMN: COMPANYID (INTEGER, Foreign key to COMPANY)
COLUMN: DELETED (INTEGER)
CHECK: DELETED = 0 OR DELETED = 1
Run Code Online (Sandbox Code Playgroud)

现在,要求允许无限删除记录,但只允许每个日期+公司的单个未删除记录。

我建议将架构更改为:

MYTABLE
COLUMN: ID (INTEGER Primary key, auto-incrementer)
COLUMN: START (DATE)
COLUMN: COMPANYID (INTEGER, Foreign key to COMPANY)
COLUMN: ACTIVE (Nullable INTEGER)
CHECK: ACTIVE = 1 OR ACTIVE IS NULL
UNIQUE: START, COMPANYID, ACTIVE
Run Code Online (Sandbox Code Playgroud)

虽然我的同事认为这“在约束上做得太过分了”,而我们应该只依赖应用程序中的唯一性检查。

这里有普遍接受的最佳实践吗?

database-design unique-constraint db2-midrange

5
推荐指数
1
解决办法
205
查看次数

当限制为一对多时,在一对多对多桥接关系中强制执行唯一性

我们定义了一系列配置,其中,在 RESTful API 的驱动下,最终用户可以构建新的修订版本。配置的某些组件可以有多个值;修订涉及具有一对多关系的多个表。

因为配置被运往别处,修订被标记为已部署,并且变得不可变。如果用户想对配置进行更改,他们必须创建一个新修订(可以从现有修订中克隆)。每个配置的一个 修订版可以标记为“当前”;这允许用户随意在过去的修订之间切换,或者通过不选择任何修订来完全禁用配置。当前版本已部署,当将不同版本标记为“当前”时,您将替换已部署的配置。

我们已经准备好了一切来强制部署修订的不变性;当您第一次使用修订作为当前修订时,该deployed列会自动转换为TRUE,并且所有进一步的INSERT,UPDATEDELETE与修订相关表中部署的修订 ID 匹配的行的操作都将被阻止。

但是,用于公共名称表中的name列的任何值在所有当前配置的所有“当前”修订中都必须是唯一的。我正在尝试找出执行此操作的最佳策略。

如果这是从配置到公共名称的简单一对多关系,则可以通过对name列使用唯一约束来解决。相反,这是一种一对多模式,revision充当桥接表,并将current_revision_id一对多对多关系“折叠”为从配置到虚拟的一对多关系公共名称。

这是一组简化的表格,用于说明我们的情况:

-- Configurations
CREATE TABLE config (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    current_revision_id INT
);

-- Have multiple revisions
CREATE TABLE revision (
    id INT PRIMARY KEY,
    config_id INT NOT NULL REFERENCES config(id),
    created_at TIMESTAMP WITH TIME ZONE …
Run Code Online (Sandbox Code Playgroud)

postgresql trigger physical-design unique-constraint

5
推荐指数
1
解决办法
155
查看次数