在SQL Server自动递增键列中包含其他字符和符号

时间:2015-07-25 09:14:35

标签: sql-server primary-key

我已经开始研究一个项目了。除基本信息外,我没有太多经验。我只想问我可以在主键列中使用符号,如2015/1234等。这些是文件编号,必须是唯一的,所以我决定将它们作为主键,但我不确定是否可以使用符号,如果我可以使用,我可以使用像

这样的自动增量
2015/1234, 2015/1235 ... etc.

2015年是年份数。第二个序列号必须在每个新年重置为1。

编辑:如果可以使用我应该使用的所有数据类型?

4 个答案:

答案 0 :(得分:1)

您可以将FileNumber的类型更改为VARCHAR(x),但假设您需要sequence part(即1234),则可以将您的文件编号设为主键每年要重置的文件号,你将无法利用标识列(Sql Server的自动递增值),因为这将在每年后继续增加。

你可以保留一个VARCHAR FileNumber PK并自己管理文件编号生成,但我建议不要这样做 - 它对并发性有害,因为两个同时插入的编写器需要争用的“下一个”值。序列号 - 这通常会导致插入前的可怕锁定SELECT MAX...查询或外部“下一个值”表,尽管在Sql Server 2012+中,a Sequence会为您管理此问题。

相反,我建议只使用代理积分标识(例如ID INT IDENTITY(1,1)作为PK - Sql Server将处理并发性,其他FK引用您的表格的范围更窄。

然后,添加您编码的自然/复合FileNumber字段,并包含一个额外的唯一键约束列,或者更好,只需将FileNumber作为两个单独的列分隔为Year int,即{{1 }和SequenceInYear int。然后,您始终可以使用计算列重新生成完整的FileNumber字符串。

<强>实施

绝对假设您无法将新文件插入OLD年,以下是我将如何执行此操作:

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开始编号,那么每年需要reset the Sequence

Sql Fiddle of this here

[Year], SequenceNoInYear上的唯一键约束将防止在序列号重置后插入旧年。

答案 1 :(得分:1)

最好的解决方案是使用

  • 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....
  )

现在,每次在tblCompany中插入一行而未指定IDCompanyID的值时:

INSERT INTO dbo.YourTable(SomeDateColumn, Col1, Col2, ..., ColN)
VALUES ('20150725', Val1, Val2, ....., ValN)

然后SQL Server将自动且安全地增加ID值,而YourCompoundID将包含00001/201500002/2015等值。 ....等等 - 自动,安全,可靠。

答案 2 :(得分:0)

自动增量(T-SQL中的identity)只能用于整数。它还限制了列的插入方式。解决您的要求的一种方法可能是将数字范围分配给特定年份(2014,2015等),然后将这些数字转换回查询中的文件名,例如: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

并将其用作查找要生成的新密钥(并且不要忘记随后更新其中的最大值)。

答案 3 :(得分:0)

你必须在你的情况下创建一个主键设置初始值1233并根据你的要求制定你的FileID只需在你的数据库中运行我的查询并尝试在表中插入manuaaly你看到你得到你的结果我希望这将帮助你

/****** 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