如何使SQL Server表主键自动增加一些字符

时间:2015-07-12 17:53:23

标签: sql-server auto-increment

我有一张这样的表:

create table ReceptionR1 
(
   numOrdre             char(20)             not null,
   dateDepot            datetime             null,
   ...
)

我希望增加我的id字段(numOrdre),例如'225/2015','226/2015',...,'1/2016'等。我应该为此做些什么?

2015表示实际年份。

请以任何可能的方式告诉我。

3 个答案:

答案 0 :(得分:1)

你真的,我的意思是真的不想做这样的事情,特别是作为你的主键。您最好为主键使用简单的int identity列,并添加类型为datetime2的非可空创建日期列,其默认值为sysDateTime()

按年计算列或使用而不是插入触发器创建增量编号(如果您不希望每次都重新计算它)。使用row_number函数可以很容易地完成这项工作。

答案 1 :(得分:1)

正如其他人所说的那样 - 不要将其用作主键!但是,如果您使用SQL Server 2012或更高版本,可以执行以下操作:

-- step 1 - create a sequence
CREATE SEQUENCE dbo.SeqOrderNo AS INT
START WITH 1001  -- start with whatever value you need
INCREMENT BY 1
NO CYCLE
NO CACHE;

-- create your table - use INT IDENTITY as your primary key
CREATE TABLE dbo.ReceptionR1 
(
   ID INT IDENTITY 
      CONSTRAINT PK_ReceptionR1 PRIMARY KEY CLUSTERED,
   dateDepot DATE NOT NULL,
   ...
   -- add a colum called "SeqNumber" that gets filled from the sequence
   SeqNumber INT,

   -- you can add a *computed* column here
   OrderNo = CAST(YEAR(dateDepot) AS VARCHAR(4)) + '/' + CAST(SeqNumber AS VARCHAR(4))
)

现在,当您插入一行时,它有一个正确的和定义良好的主键(ID),当您用SeqNumber时>

INSERT INTO dbo.ReceptionR1 (dateDepot, SeqNumber)
VALUES (SYSDATETIME(), NEXT VALUE FOR dbo.SeqOrderNo)

然后SeqNumber列获取序列的下一个值,OrderNo计算列填充2015/10012015/1002等等。

现在,当2016年出现时,您只需将序列重置为起始值:

ALTER SEQUENCE dbo.SeqOrderNo RESTART WITH 1000;

你完成了 - 你的解决方案的其余部分和以前一样。

如果您想确保永远不会意外插入重复值,您甚至可以在表格的OrderNo列中添加唯一索引。

答案 2 :(得分:0)

再一次,您不能将组合字段用作主键。此解决方案对早期版本的SQL进行排序或工作,并自动计算新的年度YearlySeq计数器 - 但您最好在dateDepot上有一个索引,如果有很多很多(100个,数千个),您可能仍会遇到问题。每年的行数。

简而言之:打击要求。

给出

create table dbo.ReceptionR1 
(
ReceptionR1ID       INT IDENTITY PRIMARY KEY,
YearlySeq           INT  ,
dateDepot           datetime  DEFAULT (GETDATE())  ,
somethingElse       varchar(99) null,
numOrdre            as LTRIM(STR(YearlySeq)) + '/' + CONVERT(CHAR(4),dateDepot,111)
) 


GO
CREATE TRIGGER R1Insert on dbo.ReceptionR1 for   INSERT
as
UPDATE tt SET YearlySeq = ISNULL(ii.ReceptionR1ID - (SELECT MIN(ReceptionR1ID) FROM  dbo.ReceptionR1 xr WHERE DATEPART(year,xr.dateDepot) = DATEPART(year,ii.dateDepot) and xr.ReceptionR1ID <> ii.ReceptionR1ID ),0) + 1
    FROM dbo.ReceptionR1 tt
        JOIN inserted ii on ii.ReceptionR1ID = tt.ReceptionR1ID 
GO

insert into ReceptionR1 (somethingElse) values ('dumb')
insert into ReceptionR1 (somethingElse) values ('requirements')
insert into ReceptionR1 (somethingElse) values ('lead')
insert into ReceptionR1 (somethingElse) values ('to')
insert into ReceptionR1 (somethingElse) values ('big')
insert into ReceptionR1 (somethingElse) values ('problems')
insert into ReceptionR1 (somethingElse) values ('later')

select * from ReceptionR1