【问题标题】:Creating a sequence for a column's value with minimum value 1 if no values exist, and 1 larger than the highest value on the column if values exist为列的值创建一个序列
【发布时间】:2017-02-28 13:18:30
【问题描述】:

我有表organisation,它有一列customer_number

现在,我应该创建一个序列,每当创建一个新的 organisation 时 - 就像在新行中持久保存到表中一样 - 新行上的 customer_numbercolumn 将获得值 1 如果没有值存在于任何行的customer_number 列中。如果值确实存在,则新行将在所述列上获得一个值,该值将是表中所述列上的最大值加一。

示例:如果在 customer_number 列上没有行或只有行没有值,则新添加的 organisation 行将获得 1 作为其 customer_number 列的值。例如,如果在所述列上已经有两行具有值 - 例如 100 和 200 - 新行将在该列上获得值 201。

我只是想不出实现这个目标的 SQL 咒语。

数据库是 SQL Server 2012。

我已经有一个 ID 序列。在创建表的 SQL 脚本中是这样的:

CREATE SEQUENCE organisation_seq AS BIGINT START WITH 1 INCREMENT BY 1;
CREATE TABLE organisation
(
  id BIGINT NOT NULL,
  customer_number VARCHAR(50) UNIQUE,
... rest of the columns ...
);

在组织实体 bean 中是这样的:

@Entity
@Table(name = "organisation")
public class Organisation {

    static Logger logger = Logger.getLogger(Organisation.class.getName());
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="organisationSeq")
    @SequenceGenerator(name="organisationSeq", sequenceName="organisation_seq", allocationSize=1)
    private Long id;

    private String customerNumber;

   ... rest of the Entity properties ...

【问题讨论】:

    标签: java sql jpa sql-server-2012 sequence


    【解决方案1】:

    如果您只是希望能够从查询确定的值开始重新启动序列,您可以使用动态 sql 执行此操作,如下所示:

    create procedure dbo.mysequence_restart as 
    begin
    set nocount, xact_abort on;
      declare @restartSequence nvarchar(256);
      declare @restartWith nvarchar(10); = convert(nvarchar(10),isnull((
        select max(id)+1 
        from organisation 
        where customer_number is not null
        ), 1));
    
      set @restartSequence = 'alter sequence dbo.mysequence restart with '+@restartWith+';'; 
      exec sp_executesql @restartSequence;
    end;
    go
    

    这不必在过程中,它只是一个例子。


    sequence 在 Sql Server 中的工作方式并不完全如此。以下是sequenceidentity 对它们未生成的插入值的反应的快速比较。

    测试设置:http://rextester.com/VDDF36095

    /* ------------- using sequence ----------- */
    create sequence organisation_seq as bigint 
      start with 1 increment by 1;
    create table organisation
    (
      id bigint not null default next value for organisation_seq,
      customer_number varchar(50) unique
    );
    
    insert into organisation values
     (next value for organisation_seq, 'a')
    ,(200, 'b')
    ,(next value for organisation_seq, 'c');
    
    select * from organisation;
    

    返回:

    +-----+-----------------+
    | id  | customer_number |
    +-----+-----------------+
    |   1 | a               |
    | 200 | b               |
    |   2 | c               |
    +-----+-----------------+
    

    如果您改用identity

    /* ------------- using identity ----------- */
    create table organisation_identity
    (
      id bigint not null identity (1,1),
      customer_number varchar(50) unique
    );
    
    insert into organisation_identity values
    ('a');
    
    /* ------------- identity_insert on ----------- */
    set identity_insert organisation_identity on;
    insert into organisation_identity (id, customer_number) values
    (200, 'b');
    set identity_insert organisation_identity off;
    /* ------------- identity_insert off ----------- */
    
    insert into organisation_identity values
    ('c');
    
    select * from organisation_identity;
    

    返回:

    +-----+-----------------+
    | id  | customer_number |
    +-----+-----------------+
    |   1 | a               |
    | 200 | b               |
    | 201 | c               |
    +-----+-----------------+
    

    序列参考:

    身份参考:

    【讨论】:

    • 伟大而彻底的答案,但这并不能解决问题。我需要更改 customer_number 列。我认为您不能更改表并在其上添加 IDENTITY 自动递增。
    • @SteveWaters 已更新为另一种选择。
    猜你喜欢
    • 2017-10-11
    • 1970-01-01
    • 2017-08-12
    • 2017-12-03
    • 2022-12-12
    • 2023-02-23
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    相关资源
    最近更新 更多