`

产生一个 类似 20110409001 这种格式的流水号

 
阅读更多

今天百度知道那里,看到个问题
说 需要一个因日期变更的归零自增字段
在今天0409他会以0409001开始无限增加,
到0410这天会以0410001开始无限增加,以此类推。。
关键是解决001这三位数怎样随日期变更而重置??

下面是测试表,只描述几个关键的字段:
也就是 
p_id :自增主键
p_year : 记录的日期
p_num : 准备作为那个流水号的字段.

create table Pdms_polling(
 p_id int primary key IDENTITY(1,1) ,
 p_year datetime ,
 p_num varchar(30) 
);
go


-- 这个是我一开始写的触发器
-- 算法是使用 ROW_NUMBER() 对 日期进行分组,按自增主键进行排序
-- 最后是形成一个按日期递增 序号的列表
-- 然后使用 right( cast(power(10,3) as varchar) + 序号, 3) 来将其格式化为 000 的格式

CREATE TRIGGER TriAutoNum
 ON Pdms_polling
FOR INSERT
AS 
  DECLARE
    @newID  INT,
    @newNum    varchar(30),
    @oldNum    varchar(30);
BEGIN
  -- 定义游标.
  DECLARE c_test_main CURSOR FAST_FORWARD FOR
    SELECT 
      p_id, 
      p_num,
      Convert(varchar(10), p_year, 112) +
      right(
        cast(power(10,3) as varchar)
        + ROW_NUMBER() OVER(PARTITION BY Convert(varchar(10), p_year, 112) ORDER BY p_id)
        , 3)
   FROM 
     Pdms_polling
   WHERE
     Convert(varchar(10), p_year, 112) 
       IN ( SELECT DISTINCT Convert(varchar(10), p_year, 112) FROM inserted );
     
  -- 打开游标.
  OPEN c_test_main;

  -- 填充数据.
  FETCH NEXT FROM c_test_main INTO @newID, @oldNum, @newNum;

  -- 假如检索到了数据,才处理.
  WHILE @@fetch_status = 0
  BEGIN
    
    IF @oldNum IS NULL BEGIN
      UPDATE
        Pdms_polling
      SET
        p_num = @newNum
      WHERE
        p_id = @newID;
    END;
    -- 填充下一条数据.
    FETCH NEXT FROM c_test_main INTO @newID, @oldNum, @newNum;
  END;
  
  -- 关闭游标
  CLOSE c_test_main;
  -- 释放游标.
  DEALLOCATE c_test_main;
END;
go




-- 下面是测试插入一条记录
1> INSERT INTO Pdms_polling (p_year) VALUES( GETDATE() );
2> go

(1 行受影响)
1>
2> SELECT * FROM Pdms_polling;
3> go
p_id        p_year                  p_num
----------- ----------------------- ------------------------------
          1 2011-04-09 22:53:32.640 20110409001

(1 行受影响)


1> -- 下面是测试插入多条记录
2> INSERT INTO Pdms_polling (p_year)
3>   SELECT GETDATE()
4>   UNION ALL SELECT GETDATE()
5>   UNION ALL SELECT GETDATE();
6> go

(1 行受影响)
1>
2> SELECT * FROM Pdms_polling;
3> go
p_id        p_year                  p_num
----------- ----------------------- ------------------------------
          1 2011-04-09 22:53:32.640 20110409001
          2 2011-04-09 22:53:32.840 20110409002
          3 2011-04-09 22:53:32.840 20110409003
          4 2011-04-09 22:53:32.840 20110409004

(4 行受影响)
1>
2> INSERT INTO Pdms_polling (p_year)
3>   SELECT '2011-04-08 10:00:00'
4>   UNION ALL SELECT '2011-04-09 10:00:00'
5>   UNION ALL SELECT '2011-04-10 10:00:00';
6> go

(1 行受影响)


1> -- 下面是测试插入多条记录 不同天的。
2> SELECT * FROM Pdms_polling;
3> go
p_id        p_year                  p_num
----------- ----------------------- ------------------------------
          1 2011-04-09 22:53:32.640 20110409001
          2 2011-04-09 22:53:32.840 20110409002
          3 2011-04-09 22:53:32.840 20110409003
          4 2011-04-09 22:53:32.840 20110409004
          5 2011-04-08 10:00:00.000 20110408001
          6 2011-04-09 10:00:00.000 20110409005
          7 2011-04-10 10:00:00.000 20110410001

(7 行受影响)




写好以后,又回去看看那个问题。
发现别人用 CTE 来处理,效果也不错。

回头我再来修改修改我的触发器,也使用 CTE 来处理。
这样就可以不用游标了。代码也简短了不少。


ALTER TRIGGER TriAutoNum
 ON Pdms_polling
FOR INSERT
AS 
BEGIN
  
  WITH
    cte
  AS
  (
    SELECT 
      p_id, 
      p_num,
      Convert(varchar(10), p_year, 112) +
      right(
        cast(power(10,3) as varchar)
        + ROW_NUMBER() OVER(PARTITION BY Convert(varchar(10), p_year, 112) ORDER BY p_id)
        , 3)  AS new_p_num
    FROM 
      Pdms_polling
    WHERE
      Convert(varchar(10), p_year, 112) 
        IN ( SELECT DISTINCT Convert(varchar(10), p_year, 112) FROM inserted )
  )
  UPDATE
    Pdms_polling
  SET
    Pdms_polling.p_num = cte.new_p_num
  FROM 
    Pdms_polling 
      JOIN cte 
      ON (Pdms_polling.p_id = cte.p_id)
  WHERE
    Pdms_polling.p_num IS NULL;

END;
go


-- 下面是测试插入一条记录
1> INSERT INTO Pdms_polling (p_year) VALUES( GETDATE() );
2> go

(1 行受影响)
1>
2> SELECT * FROM Pdms_polling;
3> go
p_id        p_year                  p_num
----------- ----------------------- ------------------------------
          1 2011-04-09 22:53:32.640 20110409001
          2 2011-04-09 22:53:32.840 20110409002
          3 2011-04-09 22:53:32.840 20110409003
          4 2011-04-09 22:53:32.840 20110409004
          5 2011-04-08 10:00:00.000 20110408001
          6 2011-04-09 10:00:00.000 20110409005
          7 2011-04-10 10:00:00.000 20110410001
          8 2011-04-09 23:10:27.687 20110409006

(8 行受影响)


1> -- 下面是测试插入多条记录
2> INSERT INTO Pdms_polling (p_year)
3>   SELECT GETDATE()
4>   UNION ALL SELECT GETDATE()
5>   UNION ALL SELECT GETDATE();
6> go

(3 行受影响)
1>
2> SELECT * FROM Pdms_polling;
3> go
p_id        p_year                  p_num
----------- ----------------------- ------------------------------
          1 2011-04-09 22:53:32.640 20110409001
          2 2011-04-09 22:53:32.840 20110409002
          3 2011-04-09 22:53:32.840 20110409003
          4 2011-04-09 22:53:32.840 20110409004
          5 2011-04-08 10:00:00.000 20110408001
          6 2011-04-09 10:00:00.000 20110409005
          7 2011-04-10 10:00:00.000 20110410001
          8 2011-04-09 23:10:27.687 20110409006
          9 2011-04-09 23:10:27.733 20110409007
         10 2011-04-09 23:10:27.733 20110409008
         11 2011-04-09 23:10:27.733 20110409009

(11 行受影响)


1> -- 下面是测试插入多条记录 不同天的。
2> INSERT INTO Pdms_polling (p_year)
3>   SELECT '2011-04-08 10:00:00'
4>   UNION ALL SELECT '2011-04-09 10:00:00'
5>   UNION ALL SELECT '2011-04-10 10:00:00';
6> go

(3 行受影响)
1>
2> SELECT * FROM Pdms_polling;
3> go
p_id        p_year                  p_num
----------- ----------------------- ------------------------------
          1 2011-04-09 22:53:32.640 20110409001
          2 2011-04-09 22:53:32.840 20110409002
          3 2011-04-09 22:53:32.840 20110409003
          4 2011-04-09 22:53:32.840 20110409004
          5 2011-04-08 10:00:00.000 20110408001
          6 2011-04-09 10:00:00.000 20110409005
          7 2011-04-10 10:00:00.000 20110410001
          8 2011-04-09 23:10:27.687 20110409006
          9 2011-04-09 23:10:27.733 20110409007
         10 2011-04-09 23:10:27.733 20110409008
         11 2011-04-09 23:10:27.733 20110409009
         12 2011-04-08 10:00:00.000 20110408002
         13 2011-04-09 10:00:00.000 20110409010
         14 2011-04-10 10:00:00.000 20110410002

(14 行受影响)

 

    原文:http://hi.baidu.com/wangzhiqing999/home

分享到:
评论

相关推荐

    流水号生成软件

    1. **唯一性**:这是流水号生成的最基本要求,确保每一个流水号在整个系统中都是唯一的,不会重复。这通常通过数据库的主键约束或者分布式锁机制来实现。 2. **可预测性**:在某些情况下,流水号需要有一定的可预测...

    abap产生流水号的两种方法

    1. 创建范围对象:使用T-Code SNRO创建一个流水号标识对象,输入对象名称,然后单击创建。 2. 设定流水号:输入Short text, Long text, Number length domain,在写程序的时候可以另外创建,编号长度域可以使用自己...

    生成并发唯一性流水号的解决方案.doc

    日期部分是使用当前日期的年月日,流水号部分是使用一个自增的数字。流水号的生成规则可以总结为:当日期相等时,加 1;当日期不相等时,重新赋值日期,流水号从 1 开始。 并发测试 并发测试是该解决方案的最后...

    java生成流水-格式202001270001

    - 考虑到业务需求可能的变化,流水号格式可以做成配置项,允许在不修改代码的情况下更改格式。 - 为了防止计数器回滚(如系统重启),可以将当前流水号持久化存储,如写入数据库或分布式缓存。 总之,"java生成...

    C#生成流水号小代码

    - **流水号格式**: `AD + 当前日期(yyyyMMdd) + 序列号` - **处理逻辑**: 1. **初始化情况**: - 如果是首次生成流水号,则返回格式为 `AD + 当前日期 + 101` 的流水号。 2. **非初始化情况**: - 检查是否有...

    自定义函数完成单据流水号的设计

    对于单据流水号生成,我们通常会选择Scalar UDF,因为它返回一个单一的值,这正是我们需要的流水号。 单据流水号的设计通常要考虑以下几个方面: 1. **唯一性**:流水号必须在数据库中是唯一的,确保每条记录都...

    一个实用的流水号编码类

    以下是对"一个实用的流水号编码类"的详细解释。 流水号(Sequential Number)通常是指按照特定顺序生成的一系列数字,它反映了数据的生成顺序,可以用来追踪记录,例如订单号、交易号等。流水号的设计通常不包含...

    mysql创建流水号

    mysql创建流水号,以前也一直不知道怎么写,最后我知道了,然后我保存了下来

    通用流水号-sql版

    流水号是现在各类系统中单据的必备字段,因为流水号很容易标识一个新的单据.例如流水号的格式为:单据前缀+业务日期+几位顺序编号.知道了流水号的固定格式,设计流水号就非常方便了.在SqlServer中,可以通过客户端程序来...

    JAVA生成订单号(日期+流水号)

    2. **流水号**:生成流水号通常需要一个全局变量,如原子整型(`AtomicInteger`),以保证在多线程环境中的安全性。初始化原子整型为0,每次生成订单号时自增1,然后取其值作为流水号: ```java AtomicInteger ...

    自动流水号打印delphi源码

    标题中的“自动流水号打印delphi源码”指的是一个使用Delphi编程语言开发的应用程序,其主要功能是自动生成并打印流水号。在IT行业中,流水号通常用于为记录分配唯一的标识符,如订单号、发票号等,以便于跟踪和管理...

    GridView加入流水号的方法.doc

    而在实际应用中,我们经常需要在`GridView`中添加一个自增的流水号列,用以标识每一行数据的顺序。本文将详细介绍如何在`GridView`中实现流水号的添加,并确保即使在开启分页的情况下,流水号仍然能够连续递增。 ##...

    SQL server 自动生成流水号

    自动为每一条插入的数据按照自己设定的格式生成流水号

    14位编号=8位日期(+6位流水号)

    流水号的长度可以根据需要而定,但在本例中,我们将实现一个14位的流水号,其中前8位为当前日期,后6位为流水号。 实现自动生成流水号的14位编号 为了实现自动生成流水号的14位编号,我们将使用SQL Server来实现。...

    生成字母流水号工具类

    根据字母生成流水号,例如当前流水号为AA,则生成新的流水号为AB。若当前流水号为AZ,则生成新的流水号为BA。若当前流水号为ZZ,则生成新的流水号为AAA。若当前流水号为空,则根据传入的位数生成初始值,以此类推。

    mysql 流水号 存储过程 附表结构

    在“mysql 流水号 存储过程 附表结构”这个主题中,我们主要探讨如何在MySQL中创建一个存储过程来生成流水号,并结合相关的表结构来实现这一功能。 流水号通常用于为数据库中的记录生成唯一的标识,它们可以是自增...

    Sql 函数获取订单交易流水号

    2. **流水号格式**: 流水号的格式通常为 `前缀+日期+顺序号`。 3. **性能考量**: 当大量并发访问时,需要考虑流水号生成的唯一性和效率问题。 4. **可扩展性**: 如果未来需要支持更多的流水号前缀或者不同的日期格式...

    流水号生成(不通过数据库)

    可以生成各种类型的不会重复的流水号,支持批量生成流水号,支持生成各个类型的流水号且互不冲突,例如给每个业务生成互不影响的流水号。 生成的流水号支持各种格式和长度,例如TB201708100001,AAS2017080001,SDB...

    彻底解决MS SQL Server2000中最大流水号的生成问题.pdf

    第一种方法是使用一个流水号辅助表来生成最大流水号。该表的结构如下所示: create table Max_trade_Id ( ID int identity(1,1) primary key ) 流水号逻辑如下: declare @myTradeId int set @myTradeId = ...

    数据库sqlservser的流水号.rar

    在本压缩包"数据库sqlservser的流水号.rar"中,包含了一个名为"流水号.sql"的文件,这很可能是用来演示或实现SQL Server中生成流水号的SQL脚本。 SQL Server 2012及更高版本引入了`SEQUENCE`对象,这是官方支持的...

Global site tag (gtag.js) - Google Analytics