我被教导不要将名称Id用于我的表的标识列,但最近我一直在使用它,因为它简单、简短并且非常描述数据的实际内容。
我见过有人建议Id使用表名作为前缀,但这似乎让编写 SQL 查询的人(或程序员,如果您使用的是像实体框架这样的 ORM)做更多的工作,尤其是在更长的表名上,例如CustomerProductId或者AgencyGroupAssignementId
我们聘请的一位第三方供应商为我们创建了一些东西,实际上命名了他们所有的身份列,Ident只是为了避免使用Id. 起初我认为他们这样做是因为Id是一个关键字,但是当我查看它时,我发现它Id不是 SQL Server 2005 中的关键字,而我们正在使用它。
那么为什么人们建议不要使用Id标识列的名称呢?
编辑:澄清一下,我不是在问要使用哪种命名约定,也不是在询问使用一种命名约定而不是另一种命名约定的参数。我只想知道为什么建议不要使用Id标识列名称。
我是一名程序员,而不是 dba,对我来说,数据库只是存储数据的地方。由于我通常构建小型应用程序,并且通常使用 ORM 进行数据访问,因此标识字段的通用字段名称更容易使用。我想知道这样做我错过了什么,以及是否有任何真正好的理由让我不这样做。
我有一个带有标识列的表说:
create table with_id (
id int identity(1,1),
val varchar(30)
);
Run Code Online (Sandbox Code Playgroud)
众所周知,这
select * into copy_from_with_id_1 from with_id;
Run Code Online (Sandbox Code Playgroud)
导致 copy_from_with_id_1 在 id 上也带有标识。
以下堆栈溢出问题提到明确列出所有列。
咱们试试吧
select id, val into copy_from_with_id_2 from with_id;
Run Code Online (Sandbox Code Playgroud)
糟糕,即使在这种情况下 id 也是一个标识列。
我想要的是一张像
create table without_id (
id int,
val varchar(30)
);
Run Code Online (Sandbox Code Playgroud) 哪个是获取我刚刚通过插入生成的标识值的最佳选择?这些语句对性能有什么影响?
SCOPE_IDENTITY() MAX()TOP 1IdentityColumn FROM TableNameORDER BY IdentityColumn DESC当根据人口统计数据匹配患者时,是否有关于哪些字段应该匹配才能使患者成为“同一患者”的建议?
我知道算法对于不同的实现会有所不同,我只是很好奇是否有关于此过程的最佳实践或建议。
First Name
Last Name
Date of Birth
SSN
Address
City
State
Zip
Run Code Online (Sandbox Code Playgroud)
等等?
TL;DR:下面的问题归结为:插入行时,在生成新Identity值和锁定聚集索引中的相应行键之间是否存在机会窗口,外部观察者可以在其中看到更新的值 Identity并发事务插入的值?(在 SQL Server 中。)
详细版
我有一个 SQL Server 表,其中有一个Identity名为的列CheckpointSequence,它是该表的聚集索引(它还具有许多其他非聚集索引)的键。行由多个并发进程和线程(在隔离级别和没有)插入到表中。同时,有进程定期从聚集索引中读取行,按该列排序(也在隔离级别,关闭该选项)。READ COMMITTEDIDENTITY_INSERTCheckpointSequenceREAD COMMITTEDREAD COMMITTED SNAPSHOT
我目前依赖于读取过程永远不能“跳过”检查点的事实。我的问题是:我可以依赖这个属性吗?如果没有,我该怎么做才能使它成为现实?
示例:当插入标识值为 1、2、3、4 和 5的行时,读者在看到值为 4 的行之前不得看到值为 5 的行。测试表明该查询包含一个ORDER BY CheckpointSequence子句 (和WHERE CheckpointSequence > -1子句),当第 4 行被读取但尚未提交时可靠地阻塞,即使第 5 行已经提交。
我相信至少在理论上,这里可能存在竞争条件,可能会导致这个假设被打破。不幸的是,Identity关于Identity在多个并发事务的上下文中如何工作的文档并没有太多说明,它只说“每个新值都是基于当前的种子和增量生成的”。和“特定事务的每个新值都不同于表上的其他并发事务。” (微软)
我的推理是,它必须以某种方式工作:
我认为在第 2 …
给定一个只有 IDENTITY 列的表,如何插入新行?我尝试了以下方法:
INSERT INTO TABLE
(Syntax error)
INSERT INTO TABLE VALUES()
(Syntax error)
INSERT INTO TABLE (Id) VALUES()
(Syntax error)
Run Code Online (Sandbox Code Playgroud)
我正在测试一些东西,只需要 IDENTITY 列。它不是用于生产。否则,这样的表可以用作序列生成器,不需要其他列。
鉴于此表:
CREATE TABLE dbo.Target (
TargetId int identity(1, 1) NOT NULL,
Color varchar(20) NOT NULL,
Action varchar(10) NOT NULL, -- of course this should be normalized
Code int NOT NULL,
CONSTRAINT PK_Target PRIMARY KEY CLUSTERED (TargetId)
);
Run Code Online (Sandbox Code Playgroud)
在两个稍微不同的场景中,我想插入行并从标识列返回值。
INSERT dbo.Target (Color, Action, Code)
OUTPUT inserted.TargetId
SELECT t.Color, t.Action, t.Code
FROM
(VALUES
('Blue', 'New', 1234),
('Blue', 'Cancel', 4567),
('Red', 'New', 5678)
) t (Color, Action, Code)
;
Run Code Online (Sandbox Code Playgroud)
CREATE TABLE #Target (
Color varchar(20) NOT NULL,
Action varchar(10) NOT NULL, …Run Code Online (Sandbox Code Playgroud) 我正在尝试生成从 1 开始并以 1 递增的唯一采购订单编号。我使用此脚本创建了一个 PONumber 表:
CREATE TABLE [dbo].[PONumbers]
(
[PONumberPK] [int] IDENTITY(1,1) NOT NULL,
[NewPONo] [bit] NOT NULL,
[DateInserted] [datetime] NOT NULL DEFAULT GETDATE(),
CONSTRAINT [PONumbersPK] PRIMARY KEY CLUSTERED ([PONumberPK] ASC)
);
Run Code Online (Sandbox Code Playgroud)
以及使用此脚本创建的存储过程:
CREATE PROCEDURE [dbo].[GetPONumber]
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[PONumbers]([NewPONo]) VALUES(1);
SELECT SCOPE_IDENTITY() AS PONumber;
END
Run Code Online (Sandbox Code Playgroud)
在创建时,这工作正常。当存储过程运行时,它从所需的数字开始并以 1 递增。
奇怪的是,如果我关闭或休眠我的计算机,那么下次运行该程序时,序列已提前了近 1000。
见下面的结果:

你可以看到数字从 8 跃升到了 1002!
我承认我不是 SQL 专家。我是否误解了 SCOPE_IDENTITY() 的作用?我应该使用不同的方法吗?我查看了 SQL 2012+ 中的序列,但微软表示默认情况下不能保证它们是唯一的。
在我正在处理的一个 Web 应用程序中,所有数据库操作都是使用一些在实体框架 ORM 上定义的通用存储库进行抽象的。
但是,为了通用存储库的简单设计,所有涉及的表都必须定义一个唯一的整数(Int32在 C# 中,int在 SQL 中)。直到现在,这一直是桌上的PK,也是IDENTITY.
外键被大量使用,它们引用这些整数列。它们对于一致性和 ORM 生成导航属性都是必需的。
应用层通常会做以下操作:
SELECT * FROM tableUPDATE table SET Col1 = Val1 WHERE Id = IdValDELETE FROM table WHERE Id = IdValINSERT INTO table (cols) VALUES (...)不太频繁的操作:
BULK INSERT ... into table后跟 (*) 所有数据加载(以检索生成的标识符)DELETE FROM table where OtherThanIdCol = SomeValue …我有一个带有 IDENTITY 列的表。在开发时,我不时删除行并再次添加它们。但是 IDENTITY 值总是不断增加并且当我再次添加它们时并没有从 1 开始。现在我的 id 从 68 -> 92 开始,这会导致我的代码崩溃。
如何重置 IDENTITY 值?
identity ×10
sql-server ×8
alter-table ×1
bulk-insert ×1
concurrency ×1
ddl ×1
insert ×1
locking ×1