字符+数字 的自动编号。

时间:2021-05-20 06:02:36
主键编号格式是   BH001,BH002,BH003.
求最好的获取新编号BH004的方法。
Delphi端orMSSQL端都可。 

14 个解决方案

#1


select 'BH' + right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa

#2


SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa

#3


引用 2 楼 zbdzjx 的回复:
SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa


没有锁表么?如果2个请求同时,会重复吧?

#4


引用 3 楼 fky1989 的回复:
Quote: 引用 2 楼 zbdzjx 的回复:

SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa


没有锁表么?如果2个请求同时,会重复吧?


只是一个参考,具体看你如何操作了。SQL Server中可以用触发器或存储过程,在保存时再生成这个号。Delphi端就是在点保存按钮时生成这个号。最主要的,这是要在数据库中这个字段上建立唯一索引,这样万一有重复,可以报错,后一个无法保存。

#5


var S:string;
    L,J:integer;
begin
  SQL:='select 主键名 from 表名';

  // 通过相关控件打印数据库 表   ......

  with DataSet do
  begin
    J:=0;
    while Not Eof do
    begin
      S:=FieldByName('主键名').AsString;
      S:=Copy(3,3);
      L:=StrToInt(S);
      if j<L then J:=L;
      Next;
    end;
  end;
  S:=Inttostr(J+1);
  while Length(S)<3 do S:='0'+S;
  S:='BH'+S;
end;


上述代码非常实用,我就是这样获取不同值有序“编码”的。仅供参考。

#6


引用 5 楼 lyhoo163 的回复:
var S:string;
    L,J:integer;
begin
  SQL:='select 主键名 from 表名';

  // 通过相关控件打印数据库 表   ......

  with DataSet do
  begin
    J:=0;
    while Not Eof do
    begin
      S:=FieldByName('主键名').AsString;
      S:=Copy(3,3);
      L:=StrToInt(S);
      if j<L then J:=L;
      Next;
    end;
  end;
  S:=Inttostr(J+1);
  while Length(S)<3 do S:='0'+S;
  S:='BH'+S;
end;


上述代码非常实用,我就是这样获取不同值有序“编码”的。仅供参考。


引用 5 楼 lyhoo163 的回复:
var S:string;
    L,J:integer;
begin
  SQL:='select 主键名 from 表名';

  // 通过相关控件打印数据库 表   ......

  with DataSet do
  begin
    J:=0;
    while Not Eof do
    begin
      S:=FieldByName('主键名').AsString;
      S:=Copy(3,3);
      L:=StrToInt(S);
      if j<L then J:=L;
      Next;
    end;
  end;
  S:=Inttostr(J+1);
  while Length(S)<3 do S:='0'+S;
  S:='BH'+S;
end;


上述代码非常实用,我就是这样获取不同值有序“编码”的。仅供参考。


不好意思表述不清。。。我是想获取数据库里最新的编号,好往数据库里插入新数据。

#7


引用 4 楼 zbdzjx 的回复:
Quote: 引用 3 楼 fky1989 的回复:

Quote: 引用 2 楼 zbdzjx 的回复:

SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa


没有锁表么?如果2个请求同时,会重复吧?


只是一个参考,具体看你如何操作了。SQL Server中可以用触发器或存储过程,在保存时再生成这个号。Delphi端就是在点保存按钮时生成这个号。最主要的,这是要在数据库中这个字段上建立唯一索引,这样万一有重复,可以报错,后一个无法保存。


只能通过报错来解决么??请问还有没有好办法啊

#8


引用 7 楼 fky1989 的回复:
Quote: 引用 4 楼 zbdzjx 的回复:

Quote: 引用 3 楼 fky1989 的回复:

Quote: 引用 2 楼 zbdzjx 的回复:

SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa


没有锁表么?如果2个请求同时,会重复吧?


只是一个参考,具体看你如何操作了。SQL Server中可以用触发器或存储过程,在保存时再生成这个号。Delphi端就是在点保存按钮时生成这个号。最主要的,这是要在数据库中这个字段上建立唯一索引,这样万一有重复,可以报错,后一个无法保存。


只能通过报错来解决么??请问还有没有好办法啊


主要就是要在数据库保存前那一刻生成这个号,这样在并发量不是特别大的时候,基本上不会重复。我之前公司是100多个用户端,基本上没碰到过因为重复报错的情况。
重复报错,只是为了防止万一有重复,这样可以避免出现问题。

还有一种方式,是建一个新表,存放表名、最后编号。如存放:table1、BH003,需要用编号时,先锁这个表,读出BH003,生成新号BH004,修改BH003为BH004,保存,解锁。BH004这个号就可以在当前记录中使用了。其他用户要生成新号,就会生成BH005了。
这种方式在大量并发时也基本上不会重复。但最好还是建立唯一索引,防止重复。

#9


觉得比较奇怪,楼主的编号才三位数,也就是说这个编号单机录入已经够应付了,就算用DELPHI的一条条记录来判断也浪费不了多少时间,没有必要想太多的。

所以,建议新建一个表,表的字段有两个:
编号:Integer(1..999);
可分配:boolean;
需要编号的时候:select top 1 From 编号表 where 可分配,当数据保存成功后,将“可分配”设置为FALSE就可以了,毕竟,你的编号只有一千个

至于MAX算法,个人的实际经验,最好放弃,我以前的实例是3个并发而已,可是每天的数据量平均是10000以上,编号的重复率为0.06%或以上。如果非得用MAX算法,最好还是把表LOCK吧。

如果实际操作中存在并发,而且不想用LOCK,最好是每个并发分配一个编号段,各自用自己的编号段+顺序号,组织编码

#10


有个想法,  是否可以将这个字段保存时,  将字段设置为自增字段.  

在取出时   格式化成   "字母" +  自增字段的数字  的方式  ? 

#11


自增字段少用。一则不符合数据库规则,数据保存时关键字段应该有值,其外不可控,不可预知情况发生

#12


要保证记录关键字段递增很难,其实实际业务中也有可能丢失的单据号,这样做无意义的。做到唯一即可。特别是关键字段有业务含义的。强烈建议不要这样做,花费和要求、兼容性巨大。

#13


无特需要求,最好还是不要用字符+流水号做KEY。你如果通过锁表处理KEY的增加,并发问题是可以解决,但是效率就降低了,
如果用程序控制,每次插入前重新读取数据库KEY值,判断是否重复,重复重新生成新KEY,效率也不会高。

#14


"可是每天的数据量平均是10000以上"
这个量很小

#1


select 'BH' + right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa

#2


SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa

#3


引用 2 楼 zbdzjx 的回复:
SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa


没有锁表么?如果2个请求同时,会重复吧?

#4


引用 3 楼 fky1989 的回复:
Quote: 引用 2 楼 zbdzjx 的回复:

SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa


没有锁表么?如果2个请求同时,会重复吧?


只是一个参考,具体看你如何操作了。SQL Server中可以用触发器或存储过程,在保存时再生成这个号。Delphi端就是在点保存按钮时生成这个号。最主要的,这是要在数据库中这个字段上建立唯一索引,这样万一有重复,可以报错,后一个无法保存。

#5


var S:string;
    L,J:integer;
begin
  SQL:='select 主键名 from 表名';

  // 通过相关控件打印数据库 表   ......

  with DataSet do
  begin
    J:=0;
    while Not Eof do
    begin
      S:=FieldByName('主键名').AsString;
      S:=Copy(3,3);
      L:=StrToInt(S);
      if j<L then J:=L;
      Next;
    end;
  end;
  S:=Inttostr(J+1);
  while Length(S)<3 do S:='0'+S;
  S:='BH'+S;
end;


上述代码非常实用,我就是这样获取不同值有序“编码”的。仅供参考。

#6


引用 5 楼 lyhoo163 的回复:
var S:string;
    L,J:integer;
begin
  SQL:='select 主键名 from 表名';

  // 通过相关控件打印数据库 表   ......

  with DataSet do
  begin
    J:=0;
    while Not Eof do
    begin
      S:=FieldByName('主键名').AsString;
      S:=Copy(3,3);
      L:=StrToInt(S);
      if j<L then J:=L;
      Next;
    end;
  end;
  S:=Inttostr(J+1);
  while Length(S)<3 do S:='0'+S;
  S:='BH'+S;
end;


上述代码非常实用,我就是这样获取不同值有序“编码”的。仅供参考。


引用 5 楼 lyhoo163 的回复:
var S:string;
    L,J:integer;
begin
  SQL:='select 主键名 from 表名';

  // 通过相关控件打印数据库 表   ......

  with DataSet do
  begin
    J:=0;
    while Not Eof do
    begin
      S:=FieldByName('主键名').AsString;
      S:=Copy(3,3);
      L:=StrToInt(S);
      if j<L then J:=L;
      Next;
    end;
  end;
  S:=Inttostr(J+1);
  while Length(S)<3 do S:='0'+S;
  S:='BH'+S;
end;


上述代码非常实用,我就是这样获取不同值有序“编码”的。仅供参考。


不好意思表述不清。。。我是想获取数据库里最新的编号,好往数据库里插入新数据。

#7


引用 4 楼 zbdzjx 的回复:
Quote: 引用 3 楼 fky1989 的回复:

Quote: 引用 2 楼 zbdzjx 的回复:

SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa


没有锁表么?如果2个请求同时,会重复吧?


只是一个参考,具体看你如何操作了。SQL Server中可以用触发器或存储过程,在保存时再生成这个号。Delphi端就是在点保存按钮时生成这个号。最主要的,这是要在数据库中这个字段上建立唯一索引,这样万一有重复,可以报错,后一个无法保存。


只能通过报错来解决么??请问还有没有好办法啊

#8


引用 7 楼 fky1989 的回复:
Quote: 引用 4 楼 zbdzjx 的回复:

Quote: 引用 3 楼 fky1989 的回复:

Quote: 引用 2 楼 zbdzjx 的回复:

SQL语句修正,如果表中没记录,自动生成BH001。
select 'BH' + case when MAX(col1) IS not null then right('00' + convert(varchar, convert(int, right(MAX(col1), 3)) + 1), 3) else '001' end from (
select 'BH001' col1
union all 
select 'BH002' col1
union all 
select 'BH003' col1
) aa


没有锁表么?如果2个请求同时,会重复吧?


只是一个参考,具体看你如何操作了。SQL Server中可以用触发器或存储过程,在保存时再生成这个号。Delphi端就是在点保存按钮时生成这个号。最主要的,这是要在数据库中这个字段上建立唯一索引,这样万一有重复,可以报错,后一个无法保存。


只能通过报错来解决么??请问还有没有好办法啊


主要就是要在数据库保存前那一刻生成这个号,这样在并发量不是特别大的时候,基本上不会重复。我之前公司是100多个用户端,基本上没碰到过因为重复报错的情况。
重复报错,只是为了防止万一有重复,这样可以避免出现问题。

还有一种方式,是建一个新表,存放表名、最后编号。如存放:table1、BH003,需要用编号时,先锁这个表,读出BH003,生成新号BH004,修改BH003为BH004,保存,解锁。BH004这个号就可以在当前记录中使用了。其他用户要生成新号,就会生成BH005了。
这种方式在大量并发时也基本上不会重复。但最好还是建立唯一索引,防止重复。

#9


觉得比较奇怪,楼主的编号才三位数,也就是说这个编号单机录入已经够应付了,就算用DELPHI的一条条记录来判断也浪费不了多少时间,没有必要想太多的。

所以,建议新建一个表,表的字段有两个:
编号:Integer(1..999);
可分配:boolean;
需要编号的时候:select top 1 From 编号表 where 可分配,当数据保存成功后,将“可分配”设置为FALSE就可以了,毕竟,你的编号只有一千个

至于MAX算法,个人的实际经验,最好放弃,我以前的实例是3个并发而已,可是每天的数据量平均是10000以上,编号的重复率为0.06%或以上。如果非得用MAX算法,最好还是把表LOCK吧。

如果实际操作中存在并发,而且不想用LOCK,最好是每个并发分配一个编号段,各自用自己的编号段+顺序号,组织编码

#10


有个想法,  是否可以将这个字段保存时,  将字段设置为自增字段.  

在取出时   格式化成   "字母" +  自增字段的数字  的方式  ? 

#11


自增字段少用。一则不符合数据库规则,数据保存时关键字段应该有值,其外不可控,不可预知情况发生

#12


要保证记录关键字段递增很难,其实实际业务中也有可能丢失的单据号,这样做无意义的。做到唯一即可。特别是关键字段有业务含义的。强烈建议不要这样做,花费和要求、兼容性巨大。

#13


无特需要求,最好还是不要用字符+流水号做KEY。你如果通过锁表处理KEY的增加,并发问题是可以解决,但是效率就降低了,
如果用程序控制,每次插入前重新读取数据库KEY值,判断是否重复,重复重新生成新KEY,效率也不会高。

#14


"可是每天的数据量平均是10000以上"
这个量很小