【问题标题】:How to make SQL Server table primary key auto increment with some characters如何使用某些字符使 SQL Server 表主键自动递增
【发布时间】:2015-09-30 23:26:04
【问题描述】:

我有一张这样的桌子:

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

我想增加我的 id 字段 (numOrdre),如 '225/2015','226/2015',...,'1/2016' 等。我应该怎么做?

2015 表示实际年份。

请告诉我任何可能的方法。

【问题讨论】:

  • 真的同时应用标签“mysql”和“sql-server”吗?
  • 我认为这是不可能的。由于您在问题中使用 MySQL 作为标签,如果您使用的是 MySQL,则可以使用 MyISAM 引擎将 2 列作为主 PRIMARY KEY (id1,id2),然后您可以创建一个视图以将两者连接到要制作的列他们看起来像你的要求。您可能会“代替视图”做的另一件事是在插入时创建触发器以生成您正在寻找的字符串。好书dba.stackexchange.com/questions/35449/…
  • 这可以完成,但不能自动完成。所需的努力是毫无意义的
  • 即使不费吹灰之力也是一个可怕的想法
  • 将数据设计与您希望数据报告的方式分开。你想达到什么目的?现在这不是一个好的数据设计。

标签: sql-server auto-increment


【解决方案1】:

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

按年份创建增量编号,作为计算列或使用代替插入触发器(如果您不希望每次都重新计算)。使用row_number 函数可以很容易地做到这一点。

【讨论】:

    【解决方案2】:

    正如其他人所说 - 不要将其用作您的主键!但如果您使用的是 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 列上放置唯一索引。

    【讨论】:

      【解决方案3】:

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

      简而言之:满足需求。

      给定

      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
      

      【讨论】:

        猜你喜欢
        • 2013-07-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多