查看用于 alter table 的 postgres 文档,似乎可以将常规约束标记为DEFERRABLE(更具体地说,INITIALLY DEFERRED,这是我感兴趣的)。
索引也可以与约束相关联,只要:
索引不能有表达式列,也不能是部分索引
这让我相信目前没有办法拥有一个具有条件的唯一索引,例如:
CREATE UNIQUE INDEX unique_booking
ON public.booking
USING btree
(check_in, check_out)
WHERE booking_status = 1;
Run Code Online (Sandbox Code Playgroud)
是INITIALLY DEFERRED,意思是,唯一性“约束”只会在交易结束时进行验证(如果SET CONSTRAINTS ALL DEFERRED;使用)。
我的假设是否正确,如果正确,有什么方法可以实现预期的行为?
谢谢
我对数据库这个主题很陌生,所以这可能听起来很无知,但我很好奇为什么应该在表中明确显示一个键。这主要是为了告诉用户给定的列值(希望)保证在每一行中都是唯一的?即使没有提到它的独特性,它也应该仍然存在。
在我们的数据库中存在一个大表,或多或少是这样的:
CREATE TABLE dbo.production_data
(
pd_id BIGINT PRIMARY KEY,
serial NVARCHAR(16) NOT NULL UNIQUE,
...
);
Run Code Online (Sandbox Code Playgroud)
但是现在串行字段的大小变得很小,所以我想将其更改为 32。Visual Studio 模式比较工具建议通过以下方式执行此操作:
DROP INDEX ux_production_data_serial ON dbo.production_data;
GO
ALTER TABLE dbo.production_data ALTER COLUMN serial NVARCHAR(32) NOT NULL;
GO
CREATE INDEX ux_production_data_serial ON dbo.production_data(serial ASC);
Run Code Online (Sandbox Code Playgroud)
这真的需要吗?或者更像是这样做的超级保存方式?
另外在重新创建唯一索引时,我的表会被锁定吗?因为这将是一个大问题(因为该表有 3000 万行,我猜重新创建索引需要相当长的时间),因为下一个维护窗口是未来几个月。我的选择是什么?
给定下表、唯一聚集索引和统计信息:
CREATE TABLE dbo.Banana
(
pk integer NOT NULL,
c1 char(1) NOT NULL,
c2 char(1) NOT NULL
);
CREATE UNIQUE CLUSTERED INDEX pk ON dbo.Banana (pk);
CREATE STATISTICS c1 ON dbo.Banana (c1);
CREATE STATISTICS c2 ON dbo.Banana (c2);
INSERT dbo.Banana
(pk, c1, c2)
VALUES
(1, 'A', 'W'),
(2, 'B', 'X'),
(3, 'C', 'Y'),
(4, 'D', 'Z');
-- Populate statistics
UPDATE STATISTICS dbo.Banana;
Run Code Online (Sandbox Code Playgroud)
在任何更新之前,统计行修改计数器显然显示为零:
-- Show statistics modification counters
SELECT
stats_name = S.[name],
DDSP.stats_id,
DDSP.[rows],
DDSP.modification_counter
FROM sys.stats AS S
CROSS …Run Code Online (Sandbox Code Playgroud) sql-server statistics execution-plan update unique-constraint
我一直在与我办公室的各种开发人员就索引的成本以及唯一性是否有益或成本高昂(可能两者兼而有之)进行持续辩论。问题的关键是我们的竞争资源。
背景
我之前读过一个讨论,该讨论指出Unique索引不需要额外的维护成本,因为Insert操作会隐式检查它适合 B 树的位置,并且如果在非唯一索引中发现重复项,则将唯一符附加到键的末尾,否则直接插入。在这一系列事件中,Unique索引没有额外成本。
我的同事反对这种说法,他说这Unique是在寻找 B 树中的新位置之后作为第二个操作强制执行的,因此比非唯一索引维护成本更高。
最坏的情况是,我见过带有标识列(固有唯一)的表,它是表的集群键,但明确声明为非唯一。最糟糕的另一方面是我对唯一性的痴迷,所有索引都被创建为唯一的,当无法定义与索引的显式唯一关系时,我将表的 PK 附加到索引的末尾以确保唯一性得到保证。
我经常参与开发团队的代码审查,我需要能够为他们提供通用的指导方针。是的,应该评估每个索引,但是当您有五台服务器,每个服务器有数千个表,而一个表上的索引多达 20 个时,您需要能够应用一些简单的规则来确保一定的质量水平。
题
Insert与维护非唯一索引的成本相比,唯一性在后端是否有额外成本?其次,将表的主键附加到索引的末尾以确保唯一性有什么问题?
示例表定义
create table #test_index
(
id int not null identity(1, 1),
dt datetime not null default(current_timestamp),
val varchar(100) not null,
is_deleted bit not null default(0),
primary key nonclustered(id desc),
unique clustered(dt desc, id desc)
);
create index
[nonunique_nonclustered_example]
on #test_index
(is_deleted)
include
(val);
create unique index
[unique_nonclustered_example]
on #test_index
(is_deleted, dt desc, id desc)
include …Run Code Online (Sandbox Code Playgroud) sql-server database-internals index-tuning unique-constraint
我有这个UNIQUE限制:
ALTER TABLE table ADD CONSTRAINT "abc123" UNIQUE
("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8");
Run Code Online (Sandbox Code Playgroud)
然后我这样做:
INSERT INTO table ("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8")
VALUES ('a', 'b', 'c', 'd', 'e', 'f', null, true);
INSERT INTO table ("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8")
VALUES ('a', 'b', 'c', 'd', 'e', 'f', null, true);
Run Code Online (Sandbox Code Playgroud)
两者都有效。两行已添加到表中。从逻辑上讲,第二个应该失败。但事实并非如此。
我究竟做错了什么?这让我发疯。
注意:如果这是我自己的数据,我将拥有一个真正独特的列,而不是这个“疯狂”的UNIQUE约束。问题是这个表保存了我的银行帐户的记录,而且他们愚蠢地在 CSV 转储中没有真正的“唯一”列,我可以用它来实际确保不插入重复的行,所以我有提出一个组合整个表中所有列以确定唯一性的方法。
在 Postgres 列上创建唯一约束是否不需要对其进行索引?
我希望自动需要一个索引来有效地维护约束。
这是一个简单的表,其中记录可以引用同一个表中的父记录:
CREATE TABLE foo (
id SERIAL PRIMARY KEY,
parent_id INT NULL,
num INT NOT NULL,
txt TEXT NULL,
FOREIGN KEY (parent_id) REFERENCES foo(id)
);
Run Code Online (Sandbox Code Playgroud)
由于增加了其他字段值之一 ( num) 在父记录和子记录之间必须相同的要求,我认为复合外键应该可以解决问题。我将最后一行更改为
FOREIGN KEY (parent_id, num) REFERENCES foo(id, num)
Run Code Online (Sandbox Code Playgroud)
并得到错误:没有唯一约束匹配给定键的引用表 "foo"。
我可以很容易地添加这个约束,但我不明白为什么它是必要的,当引用的列 ( id) 之一已经保证是唯一的?在我看来,新的约束将是多余的。
我是一名“偶然”的 DBA,相对缺乏经验并且对这个问题感到困惑。
运行 MS SQL Server 2012。问题在于这个 UPDATE 语句:
UPDATE dbo.tAccts SET
Ticket = 'ARP.ExGE'
, Method = 'smtp'
, AcctOwner = 'r00417819'
, DisplayName = '~AppLight HBSFax-Inactive'
, Destination = 'r00417819@mail.ad.ge.com'
, UpdatedBy = SYSTEM_USER
, UpdatedOn = CAST(GetDate() AS DATE)
FROM dbo.vReclaimable
WHERE OHR_EmpStatus <> 'A'
Run Code Online (Sandbox Code Playgroud)
这应该只更新tAccts 表中由 vReclaimable 视图返回的行。
vReclaimable 视图基于 tAccts 表并返回 tAccts 中行的子集。
当我运行它时,它失败并显示唯一键错误:
(0 row(s) affected)
Msg 2627, Level 14, State 1, Line 67
Violation of UNIQUE KEY constraint 'UQ__tAccounts_DNIS.Method.Destination.Phones'. Cannot …Run Code Online (Sandbox Code Playgroud) 我有一个带有唯一键的表,其中包含一NVARCHAR(50)列(正确与否,但在那里)。因此,当尝试插入?c或C(与插入顺序无关)时,由于整理问题,它会在第二次插入时中断。这是错误:
(受影响的 1 行)消息 2601,级别 14,状态 1,第 16 行无法在具有唯一索引“IX_TestT”的对象“dbo.testT”中插入重复的关键行。重复的键值为 (C)。
选择退货:
数据库默认排序规则是Latin1_General_CI_AS. 花了一些时间寻找如何解决它,而不会对现有结构进行太多更改,但找不到开始工作的方法。尝试了不同的排序规则和组合,一切都失败了。阅读(这里和这里)关于字符扩展等,仍然卡住了。这是我用来复制问题的示例代码,请随时修改并推荐任何有助于解决此问题的内容。
CREATE TABLE testT (
[Default_Collation] [NVARCHAR] (50) COLLATE DATABASE_DEFAULT,
[Latin1_General_CI_AS] [NVARCHAR] (50) COLLATE Latin1_General_CI_AS,
[Latin1_General_CI_AI] [NVARCHAR] (50) COLLATE Latin1_General_CI_AI,
[SQL_Collation] [NVARCHAR] (50) COLLATE SQL_Latin1_General_CP1_CI_AS);
CREATE UNIQUE CLUSTERED INDEX [IX_TestT] ON [dbo].[testT] ([Default_Collation])
ON [PRIMARY]
GO
INSERT INTO testT
SELECT N'?c', --COLLATE Latin1_General_CI_AS
N'?c', --COLLATE Latin1_General_CI_AS
N'?c', --COLLATE Latin1_General_CI_AS
N'?c' --COLLATE Latin1_General_CI_AS
INSERT INTO testT
SELECT …Run Code Online (Sandbox Code Playgroud) sql-server collation t-sql sql-server-2014 unique-constraint
sql-server ×5
postgresql ×4
index ×3
constraint ×2
update ×2
alter-table ×1
collation ×1
foreign-key ×1
index-tuning ×1
locking ×1
null ×1
primary-key ×1
statistics ×1
t-sql ×1
transaction ×1
view ×1