表tb1的主键为id,是VARCHAR格式,形式为20110101000001,即年月日+6位流水号,该主键非自增,但插入新纪录的时候,我要得到当天最大的ID,并加1,如当天(如2011年11月08日)还没有数据,则从20111108000001开始。我写了一个获取函数,每次都SELECT MAX 然后切割后6位再加1再拼字符串,可以得到,但效率不高,如插入1000条数据,每次都要SELECT MAX tb1一次,tb1数据量又大,非常低效。请问有什么方法可以既高效,又能保证插入数据时ID一定不会重复。
http://blog.csdn.net/roy_88/article/details/1424370
你这样做法的效率并非很差,不过得注意防止并发错误,即有个同时读取ID并也同时生成一个相同的ID.一般解决的办法是加事务.
简单的办法,还是用自增列,你用一个自增列,加一个日期列,数据处理上要比你这样处理好上百倍,为什么不这么去做呢?
http://topic.csdn.net/u/20111030/18/8e4c77b0-7a88-4276-ba52-b9e7810a5e3d.html
数据库里有编号字段
BH00001
BH00002
BH00003
BH00004
如何实现自动增长 --下面的代码生成长度为8的编号,编号以BH开头,其余6位为流水号。
--得到新编号的函数
CREATE FUNCTION f_NextBH()
RETURNS char(8)
AS
BEGIN
RETURN(SELECT 'BH'+RIGHT(1000001+ISNULL(RIGHT(MAX(BH),6),0),6) FROM tb WITH(XLOCK,PAGLOCK))
END
GO--在表中应用函数
CREATE TABLE tb(
BH char(8) PRIMARY KEY DEFAULT dbo.f_NextBH(),
col int)--插入资料
BEGIN TRAN
INSERT tb(col) VALUES(1)
INSERT tb(col) VALUES(2)
INSERT tb(col) VALUES(3)
DELETE tb WHERE col=3
INSERT tb(col) VALUES(4)
INSERT tb(BH,col) VALUES(dbo.f_NextBH(),14)
COMMIT TRAN--显示结果
SELECT * FROM tb
/*--结果
BH col
---------------- -----------
BH000001 1
BH000002 2
BH000003 4
BH000004 14
--*/ create table tb
(id int identity,
name varchar(10),
code as 'BH'+right('0000'+cast(id as varchar),5))
go
insert tb(name) select 'A'
union all select 'B'
union all select 'C'
union all select 'D'select * from tbdrop table tb/*
id name code
----------- ---------- ------------
1 A BH00001
2 B BH00002
3 C BH00003
4 D BH00004(所影响的行数为 4 行)
*/
create table tb(id char(14),col varchar(10))
insert into tb select '20111107000001','aaa'
insert into tb select '20111108000001','bbb'
go
--以下为触发器
create trigger addid
on tb
instead of insert
as
begin
set nocount oninsert into tb
select (
select convert(varchar(8),getdate(),112)+'00000'+ltrim(isnull(max(right(id,6)),0)+1)
from tb where id like convert(varchar(8),getdate(),112)+'%'),COL from inserted
end
go
--插入测试
insert into tb(col) select 'ccc'
select * from tb
/*
id col
-------------- ----------
20111107000001 aaa
20111108000001 bbb
20111108000002 ccc(3 行受影响)
*/
--删除今日数据后再插入,测试 1 的生成
delete from tb where id like convert(varchar(8),getdate(),112)+'%'
select * from tb
/*
id col
-------------- ----------
20111107000001 aaa(1 行受影响)
*/
insert into tb(col) select 'ccc'
select * from tb
/*
id col
-------------- ----------
20111107000001 aaa
20111108000001 ccc(2 行受影响)
*/
go
drop table tb
--创建例表
create table tb(id char(14),col varchar(10))
insert into tb select '20111107000001','aaa'
insert into tb select '20111108000001','bbb'
go
--以下为触发器
create trigger addid
on tb
instead of insert
as
begin
set nocount ondeclare @n int
select @n=isnull(max(right(id,6)),0) from tb where id like convert(varchar(8),getdate(),112)+'%'
insert into tb
select convert(varchar(8),getdate(),112)+'00000'+ltrim(rn+@n),col from
(select row_number()over(order by(select 1))rn,col from inserted)t
end
go
--插入测试
insert into tb(col)
select 'ccc' union all
select 'fff' union all
select 'ggg'
select * from tb
/*
id col
-------------- ----------
20111107000001 aaa
20111108000001 bbb
20111108000002 ccc
20111108000003 fff
20111108000004 ggg(5 行受影响)
*/
--删除今日数据后再插入,测试 1 的生成
delete from tb where id like convert(varchar(8),getdate(),112)+'%'
select * from tb
/*
id col
-------------- ----------
20111107000001 aaa(1 行受影响)
*/
insert into tb(col)
select 'ccc' union all
select 'fff' union all
select 'ggg'
select * from tb
/*
id col
-------------- ----------
20111107000001 aaa
20111108000001 ccc
20111108000002 fff
20111108000003 ggg(4 行受影响)
*/
go
drop table tb