今天百度知道那里,看到个问题
说 需要一个因日期变更的归零自增字段
在今天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. **可预测性**:在某些情况下,流水号需要有一定的可预测...
1. 创建范围对象:使用T-Code SNRO创建一个流水号标识对象,输入对象名称,然后单击创建。 2. 设定流水号:输入Short text, Long text, Number length domain,在写程序的时候可以另外创建,编号长度域可以使用自己...
日期部分是使用当前日期的年月日,流水号部分是使用一个自增的数字。流水号的生成规则可以总结为:当日期相等时,加 1;当日期不相等时,重新赋值日期,流水号从 1 开始。 并发测试 并发测试是该解决方案的最后...
- 考虑到业务需求可能的变化,流水号格式可以做成配置项,允许在不修改代码的情况下更改格式。 - 为了防止计数器回滚(如系统重启),可以将当前流水号持久化存储,如写入数据库或分布式缓存。 总之,"java生成...
- **流水号格式**: `AD + 当前日期(yyyyMMdd) + 序列号` - **处理逻辑**: 1. **初始化情况**: - 如果是首次生成流水号,则返回格式为 `AD + 当前日期 + 101` 的流水号。 2. **非初始化情况**: - 检查是否有...
对于单据流水号生成,我们通常会选择Scalar UDF,因为它返回一个单一的值,这正是我们需要的流水号。 单据流水号的设计通常要考虑以下几个方面: 1. **唯一性**:流水号必须在数据库中是唯一的,确保每条记录都...
以下是对"一个实用的流水号编码类"的详细解释。 流水号(Sequential Number)通常是指按照特定顺序生成的一系列数字,它反映了数据的生成顺序,可以用来追踪记录,例如订单号、交易号等。流水号的设计通常不包含...
mysql创建流水号,以前也一直不知道怎么写,最后我知道了,然后我保存了下来
流水号是现在各类系统中单据的必备字段,因为流水号很容易标识一个新的单据.例如流水号的格式为:单据前缀+业务日期+几位顺序编号.知道了流水号的固定格式,设计流水号就非常方便了.在SqlServer中,可以通过客户端程序来...
在SQL数据库中,可以通过创建一个带有`IDENTITY`属性的字段来实现这一功能。例如: ```sql CREATE TABLE MyTable ( Id INT IDENTITY(1,1) PRIMARY KEY, -- 其他字段 ) ``` 在C#和ASP.NET中,你可以使用ADO.NET...
2. **流水号**:生成流水号通常需要一个全局变量,如原子整型(`AtomicInteger`),以保证在多线程环境中的安全性。初始化原子整型为0,每次生成订单号时自增1,然后取其值作为流水号: ```java AtomicInteger ...
标题中的“自动流水号打印delphi源码”指的是一个使用Delphi编程语言开发的应用程序,其主要功能是自动生成并打印流水号。在IT行业中,流水号通常用于为记录分配唯一的标识符,如订单号、发票号等,以便于跟踪和管理...
而在实际应用中,我们经常需要在`GridView`中添加一个自增的流水号列,用以标识每一行数据的顺序。本文将详细介绍如何在`GridView`中实现流水号的添加,并确保即使在开启分页的情况下,流水号仍然能够连续递增。 ##...
自动为每一条插入的数据按照自己设定的格式生成流水号
流水号的长度可以根据需要而定,但在本例中,我们将实现一个14位的流水号,其中前8位为当前日期,后6位为流水号。 实现自动生成流水号的14位编号 为了实现自动生成流水号的14位编号,我们将使用SQL Server来实现。...
例如,我们可以使用当前时间的毫秒数加上一个自增序列,通过一定的格式化处理,形成易于识别的流水号。在C#中,可以利用`DateTime.Now.Ticks`获取时间戳,`Interlocked.Increment`用于线程安全地增加序列号。 下面...
根据字母生成流水号,例如当前流水号为AA,则生成新的流水号为AB。若当前流水号为AZ,则生成新的流水号为BA。若当前流水号为ZZ,则生成新的流水号为AAA。若当前流水号为空,则根据传入的位数生成初始值,以此类推。
在“mysql 流水号 存储过程 附表结构”这个主题中,我们主要探讨如何在MySQL中创建一个存储过程来生成流水号,并结合相关的表结构来实现这一功能。 流水号通常用于为数据库中的记录生成唯一的标识,它们可以是自增...
2. **流水号格式**: 流水号的格式通常为 `前缀+日期+顺序号`。 3. **性能考量**: 当大量并发访问时,需要考虑流水号生成的唯一性和效率问题。 4. **可扩展性**: 如果未来需要支持更多的流水号前缀或者不同的日期格式...
可以生成各种类型的不会重复的流水号,支持批量生成流水号,支持生成各个类型的流水号且互不冲突,例如给每个业务生成互不影响的流水号。 生成的流水号支持各种格式和长度,例如TB201708100001,AAS2017080001,SDB...