Sql server 在SQL Server自动递增键列中包含其他字符和符号
我开始做一个项目。除了基本信息,我没有很多经验。我只是想问一下,我可以在主键列中使用符号吗,如Sql server 在SQL Server自动递增键列中包含其他字符和符号,sql-server,primary-key,Sql Server,Primary Key,我开始做一个项目。除了基本信息,我没有很多经验。我只是想问一下,我可以在主键列中使用符号吗,如2015/1234等。这些是文件号,必须是唯一的,所以我决定将它们设为主键,但我不确定我是否可以使用符号,如果可以,我可以使用自动递增吗 2015/1234, 2015/1235 ... etc. 其中2015是一个年份数字。每年第二个序列号必须重置为1 编辑:如果可以完成所有操作,我应该使用哪种数据类型?自动递增(identity在T-SQL中)只能用于整数。它还限制了列插入的方式。解决您的需求的一
2015/1234
等。这些是文件号,必须是唯一的,所以我决定将它们设为主键,但我不确定我是否可以使用符号,如果可以,我可以使用自动递增吗
2015/1234, 2015/1235 ... etc.
其中2015是一个年份数字。每年第二个序列号必须重置为1
编辑:如果可以完成所有操作,我应该使用哪种数据类型?自动递增(identity
在T-SQL中)只能用于整数。它还限制了列插入的方式。解决您的需求的一种方法可能是将数字范围指定给特定年份(20142015等),然后在查询中将这些数字转换回文件名,例如:2014年为1-1000000,2015年为1000001-2000000,等等。在select语句中,可以使用
Select cast(floor(id/1000000)+2014 as char(4))+'/'+cast(id % 1000000 as varchar(6)) mykey ... from table
但一般来说,我认为最好使用单独的编号表,如
mumtbl:
----------
year mxidx_used
---------------------
2014 234
2015 1678
并将其用作要生成的新键的查找(之后不要忘记更新其中的最大值)。您可以通过将
FileNumber
的类型更改为VARCHAR(x)
,但假设您需要序列部分(即1234
),将您的文件号设置为主键您将无法利用标识列(Sql Server的自动递增值),因为这将在每年之后继续增加
您可以保留一个VARCHAR FileNumber
PK并自己管理文件号生成,但我建议您不要这样做-这对并发性有害,因为两个写入程序同时插入需要争夺序列号的“下一个”值-这通常会导致可怕的,已锁定SELECT MAX..。
insert前的查询或外部“next value”表(尽管在Sql Server 2012+中)将为您管理此操作
相反,我建议只使用代理整数标识(例如,ID INT-identity(1,1)
作为PK-Sql Server将处理并发性,其他FK引用您的表的范围更窄
然后,添加编码的natural/compositeFileNumber
字段,并包含一个额外的唯一键约束列,或者更好,只需将FileNumber
作为两个单独的列分解到其组成部分,即Year int
和SequenceInYear int
。然后,您可以始终使用计算列重新生成完整的FileNumber
字符串
实施
在绝对假设您无法将新文件插入旧年份的情况下,我将这样做:
CREATE SEQUENCE NextValueForCurrentYear
START WITH 1
INCREMENT BY 1 ;
CREATE TABLE MyTable
(
-- Narrow surrogate key managed by Sql
ID INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_MyTable PRIMARY KEY,
-- Provided during insert, or retrieved from some config table
[Year] INT NOT NULL,
-- Auto incrementing sequence
SequenceNoInYear INT NOT NULL CONSTRAINT DF_SequenceNoInYear
DEFAULT NEXT value FOR NextValueForCurrentYear,
-- Computed column - can be read, generated automatically
FileNumber AS CAST([Year] AS VARCHAR(4)) + '/' +
CAST(SequenceNoInYear AS VARCHAR(10)),
-- Other Columns here
-- Ensure filenumber is unique
CONSTRAINT UQ_MyTable UNIQUE([Year], SequenceNoInYear)
);
您所需要做的就是提供年份号,剩下的将被生成,即
INSERT INTO MyTable(Year) VALUES (2015);
如果您需要从1开始每年的序列号,那么您将需要每年
[Year],SequenceNoInYear上的唯一键约束将防止在序列号重置后插入旧年份。最好的解决方案是使用
- 一个
ID INT-IDENTITY(1,1)
列,用于让SQL Server处理数值的自动增量
- 一个计算的、持久的列,用于将该数值转换为所需的值
所以试试这个:
CREATE TABLE dbo.YourTable
(ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
SomeDateColumn DATE,
YourCompoundID AS RIGHT('00000' + CAST(ID AS VARCHAR(5)), 5) + '/' + CAST(YEAR(SomeDateColumn) AS VARCHAR(4)) PERSISTED,
.... your other columns here....
)
现在,每次在未指定ID
或CompanyID
值的情况下将行插入tblCompany
:
INSERT INTO dbo.YourTable(SomeDateColumn, Col1, Col2, ..., ColN)
VALUES ('20150725', Val1, Val2, ....., ValN)
然后,SQL Server将自动且安全地增加您的ID
值,YourCompoundID
将包含00001/2015
,00002/2015
,……等值-自动、安全、可靠。您必须在案例和公式中创建一个主键集初始值1233根据您的要求生成您的文件ID只需在数据库中运行我的查询,并尝试手动在表中插入名称,您就会看到结果,我希望这将对您有所帮助
/****** Object: Table [dbo].[tblStringPrimaryKey] Script Date: 7/25/2015 3:32:42 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tblStringPrimaryKey](
[Id] [int] IDENTITY(1233,1) NOT NULL,
[FileId] AS ((CONVERT([nvarchar](10),datepart(year,getdate()))+'/')+CONVERT([nvarchar](22),[Id])),
[Name] [nvarchar](50) NULL,
CONSTRAINT [PK_tblStringPrimaryKey] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_tblStringPrimaryKey] UNIQUE NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
是2015年我必须作为前缀,还是它将随着2016年的变化而变化?是的,它将随着2016年、2017年的变化而变化…看我的答案,只是在你的数据库中作为测试表运行,你得到了结果你的序列号需要在每一年开始时重置回1吗?是的,它必须重置为1谢谢你的答复我了解大部分内容,但我不知道nt询问是否从每个1开始year@ulmotl:在这种情况下,您需要一个从SQL Server 2012开始提供的序列
;您可以在需要时重置序列,例如@StuartLC提到的每新年1月1日重置一次,我想首先感谢您的回复,在SQL fiddle中,它可以正常工作,但我想询问文件编号ber,它不是表上的id号,我想它不会以这种方式是唯一的,对吗?我的意思是,如果它能工作,它会自动增加吗?谢谢:)?但是我不明白你提到的过去的岁月。如果你这么说的话,我会为存档创建另一个表。虽然Filenumber是唯一的,但它不是主键IMO的好选择。我的回答显示了如何使用序列和计算列安全地派生唯一的文件号,尽管你每年都需要重置序列。存储年份和序列时,无需存档数据。旧年份的意思是,如果我们现在是2016年,序列已经重置,因此如果您需要插入一条被遗忘的2015年记录,您需要手动确定唯一的序列号,而不是使用序列默认值。