关于自动生成唯一性ID的问题

时间:2022-09-23 12:36:48
我正在用ado+access做一个关于图书的小系统。我想在新增图书的时候,调用insert方法后,自动生成新图书的唯一性代码?请问怎么实现???如果要是人工生成的化,太麻烦了,图书多了的话,用户也不知道哪个ID是可用的,哪个是已经用的了。
我试着用了ACCESS的自动编码类型的字段但实在是太烂了,而且在INSERT时,该字段对应的DBEdit是不可见的(而且不能编辑),最好不用自动编码类型的字段。而用文本型的(00000001~~99999999),求助一个较好的自动生成图书ID代码的方法(算法)。

29 个解决方案

#1


function GetGUID:string;
var
 id:tguid;
begin
 if CoCreateGuid(id)=s_ok then
  result:=guidtostring(id);
end;

#2


理论上几乎没有重复的可能。

#3


function CoCreateGuid(out guid: TGUID): HResult; stdcall; external 'ole32.dll' name 'CoCreateGuid';

#4


又学了一招!

#5


还可以在数据库后端, 定义一个触发器, 通过生成器自动生成字段.

#6


还是用触发器把

GUID太长

#7


在程序里写自动编号的方法

#8


formatdataTime('YYYYMMDDHHmmss',now)+inttostr(random('99999'));

#9


还有没有更好的方法???最好是生成的ID在00000000~~~99999999之间就更好了。

#10


自动编号或者用条形码

#11


没必要guid吧..

#12


求表中最大记录号。

#13


GUID 太长了,可以根据系统当前的年月日再加上时间就可以生成唯一的id了

#14


求最大记录号

#15


可以建一个表,作为流水帐号。每插入一条记录,先取流水帐号表的ID,在修改流水帐号表的ID,使它加一,这样取出来的ID号就不可能有重复的了

#16


可以建一个表,作为流水帐号。每插入一条记录,先取流水帐号表的ID,在修改流水帐号表的ID,使它加一,这样取出来的ID号就不可能有重复的了
-----------------------------------------------------------对的
如果是并发的可以用存储过程来控制生成
过程实现的:计算最大id,更新表id=id+1,返回最大id+1给客户端程序

#17


给我分吧,我分太少了!!

function GetNextRecNo(var ATableName,AFieldName,ACondition,
                       ADesFieldName:String;AFieldLen:integer):String;
var
  lMax,I:Integer;
  lID,lDef:String;
  myQuery:TAdoQuery;
begin
  lDef:= '000000000000000';
  SetLength(lDef,AFieldLen-1);
  myQuery:=TAdoQuery.Create(nil);
  try
  //---- ×Ô¶¯¼ÓÈë±àºÅ
   with myQuery do
   begin
     SQL.Clear;
     if ACondition<>'' then
       SQL.Add('Select Distinct '+AFieldName+' from '+TableName+' where '+ACondition+' Order By '+ADesFieldName+' Desc')
     else
       SQL.Add('Select Distinct '+AFieldName+' from '+TableName+' Order By '+ADesFieldName+' Desc');
     Open;
     if ADesFieldName='' then ADesFieldName:=AFieldName;
     if not eof then
     begin
      lMax:=StrToInt('0'+FieldByName(ADesFieldName).AsString);
      if RecordCount=lMax then
      lID:= Copy(lDef+IntToStr(RecordCount+1),Length(lDef+IntToStr(RecordCount+1))-(AFieldLen-1),AFieldLen)
     else
       begin
          for I:=RecordCount downto 0 Do
          begin
            lMax:=StrToInt('0'+FieldByName(ADesFieldName).AsString);
            if I=lMax then begin
            lID:= Copy(lDef+IntToStr(I+1),Length(lDef+IntToStr(I+1))-(AFieldLen-1),AFieldLen);
            Break;
          end
        else
          Next;
          if I=0 then lID:=lDef+'1';
        end;
      end;
     end else
       lID:=lDef+'1';
       Close;
     end;
       Result:= lID;
    finally
       myQuery.Free;
    end;
end;

#18


guid 
time
no++
...

#19


用select count(*) as rowcount from XXXX计算表中的行数
所得结果加一
插入时用它做ID
good luck

#20


恩,呵呵~~~~~~hkbarton(→Beginner←) 的方法是个好的办法,wuxiangyang() 的方法看了半天没看懂,能给些注释吗??我感觉也有点太麻烦了,呵呵~~~~上面有人说采用条形码的方法,说仔细些???怎么样生成条形码???

#21


hkbarton(→Beginner←) 的方法我以前也用,但不能保证唯一,如果用户修改了时间呢?如果是多用户呢?

#22


miky(miky) 说的有道理。就没什么好的办法吗??继续关注。。。。。。

#23


可以建一个表,作为流水帐号。每插入一条记录,先取流水帐号表的ID,在修改流水帐号表的ID,使它加一,这样取出来的ID号就不可能有重复的了
-----------------------------------------------------------对的
如果是并发的可以用存储过程来控制生成
过程实现的:计算最大id,更新表id=id+1,返回最大id+1给客户端程序
----

完全同意
GUID太长了,自增字段问题多多。用时间既不安全,也有些长,影响效率。

#24


可以建一个表,作为流水帐号。每插入一条记录,先取流水帐号表的ID,在修改流水帐号表的ID,使它加一,这样取出来的ID号就不可能有重复的了
-----------------------------------------------------------对的
如果是并发的可以用存储过程来控制生成
过程实现的:计算最大id,更新表id=id+1,返回最大id+1给客户端程序
----

这不正是自增字段为我们做的吗?

我不明白自增字段有什么问题,我觉得非常好用。

只有一种情况,就是你有多个不连网的客户端,为了保证他们的数据ID也不重复,这时候才不能用。

#25


自增字段在用DBEdit开发时,如果你调用了ADOTable.Append;方法后,该DBEdit上Text内容是不可见的(不能让用户立即看见新生成的流水号)。只有保存后POST才能看见。我想让它马上显示出新增的ID。另外本人用是access+ado是个单机的系统,求教好的方法!!!

#26


那你不能不用DBedit吗?怎么能怪到自增字段的头上呢?
其实什么DBedit,DBGrid之类的,会给你的开发带来很大的限制,想要方便,就必须放弃一定的*度,有得必有失。

#27


呵呵~~各位我已经想出来个办法了,可能比较蠢,但挺灵的,请各位指教。

//ID为ACCESS中的长整形字段,代表图书的唯一性代码

procedure TForm1.Button1Click(Sender: TObject);
var
  j,k: Integer;
begin
  ADOTable1.Sort:='ID ASC';
  ADOTable1.First;
  j:=ADOTable1['ID'];
  ADOTable1.Next;
  k:=ADOTable1['ID'];

  while (k-j=1) do
  begin
    j:=k;
    ADOTable1.Next;
    k:=ADOTable1['ID'];
  end;

  Edit1.Text:=Inttostr(j+1);

#28


可能我的办法有点笨了。呵呵~~~~~自动查找到不连续的那个ID的开始处,然后插入新的ID号。

#29


identity

#1


function GetGUID:string;
var
 id:tguid;
begin
 if CoCreateGuid(id)=s_ok then
  result:=guidtostring(id);
end;

#2


理论上几乎没有重复的可能。

#3


function CoCreateGuid(out guid: TGUID): HResult; stdcall; external 'ole32.dll' name 'CoCreateGuid';

#4


又学了一招!

#5


还可以在数据库后端, 定义一个触发器, 通过生成器自动生成字段.

#6


还是用触发器把

GUID太长

#7


在程序里写自动编号的方法

#8


formatdataTime('YYYYMMDDHHmmss',now)+inttostr(random('99999'));

#9


还有没有更好的方法???最好是生成的ID在00000000~~~99999999之间就更好了。

#10


自动编号或者用条形码

#11


没必要guid吧..

#12


求表中最大记录号。

#13


GUID 太长了,可以根据系统当前的年月日再加上时间就可以生成唯一的id了

#14


求最大记录号

#15


可以建一个表,作为流水帐号。每插入一条记录,先取流水帐号表的ID,在修改流水帐号表的ID,使它加一,这样取出来的ID号就不可能有重复的了

#16


可以建一个表,作为流水帐号。每插入一条记录,先取流水帐号表的ID,在修改流水帐号表的ID,使它加一,这样取出来的ID号就不可能有重复的了
-----------------------------------------------------------对的
如果是并发的可以用存储过程来控制生成
过程实现的:计算最大id,更新表id=id+1,返回最大id+1给客户端程序

#17


给我分吧,我分太少了!!

function GetNextRecNo(var ATableName,AFieldName,ACondition,
                       ADesFieldName:String;AFieldLen:integer):String;
var
  lMax,I:Integer;
  lID,lDef:String;
  myQuery:TAdoQuery;
begin
  lDef:= '000000000000000';
  SetLength(lDef,AFieldLen-1);
  myQuery:=TAdoQuery.Create(nil);
  try
  //---- ×&Ocirc;&para;&macr;&frac14;&Oacute;&Egrave;&euml;±à&ordm;&Aring;
   with myQuery do
   begin
     SQL.Clear;
     if ACondition<>'' then
       SQL.Add('Select Distinct '+AFieldName+' from '+TableName+' where '+ACondition+' Order By '+ADesFieldName+' Desc')
     else
       SQL.Add('Select Distinct '+AFieldName+' from '+TableName+' Order By '+ADesFieldName+' Desc');
     Open;
     if ADesFieldName='' then ADesFieldName:=AFieldName;
     if not eof then
     begin
      lMax:=StrToInt('0'+FieldByName(ADesFieldName).AsString);
      if RecordCount=lMax then
      lID:= Copy(lDef+IntToStr(RecordCount+1),Length(lDef+IntToStr(RecordCount+1))-(AFieldLen-1),AFieldLen)
     else
       begin
          for I:=RecordCount downto 0 Do
          begin
            lMax:=StrToInt('0'+FieldByName(ADesFieldName).AsString);
            if I=lMax then begin
            lID:= Copy(lDef+IntToStr(I+1),Length(lDef+IntToStr(I+1))-(AFieldLen-1),AFieldLen);
            Break;
          end
        else
          Next;
          if I=0 then lID:=lDef+'1';
        end;
      end;
     end else
       lID:=lDef+'1';
       Close;
     end;
       Result:= lID;
    finally
       myQuery.Free;
    end;
end;

#18


guid 
time
no++
...

#19


用select count(*) as rowcount from XXXX计算表中的行数
所得结果加一
插入时用它做ID
good luck

#20


恩,呵呵~~~~~~hkbarton(→Beginner←) 的方法是个好的办法,wuxiangyang() 的方法看了半天没看懂,能给些注释吗??我感觉也有点太麻烦了,呵呵~~~~上面有人说采用条形码的方法,说仔细些???怎么样生成条形码???

#21


hkbarton(→Beginner←) 的方法我以前也用,但不能保证唯一,如果用户修改了时间呢?如果是多用户呢?

#22


miky(miky) 说的有道理。就没什么好的办法吗??继续关注。。。。。。

#23


可以建一个表,作为流水帐号。每插入一条记录,先取流水帐号表的ID,在修改流水帐号表的ID,使它加一,这样取出来的ID号就不可能有重复的了
-----------------------------------------------------------对的
如果是并发的可以用存储过程来控制生成
过程实现的:计算最大id,更新表id=id+1,返回最大id+1给客户端程序
----

完全同意
GUID太长了,自增字段问题多多。用时间既不安全,也有些长,影响效率。

#24


可以建一个表,作为流水帐号。每插入一条记录,先取流水帐号表的ID,在修改流水帐号表的ID,使它加一,这样取出来的ID号就不可能有重复的了
-----------------------------------------------------------对的
如果是并发的可以用存储过程来控制生成
过程实现的:计算最大id,更新表id=id+1,返回最大id+1给客户端程序
----

这不正是自增字段为我们做的吗?

我不明白自增字段有什么问题,我觉得非常好用。

只有一种情况,就是你有多个不连网的客户端,为了保证他们的数据ID也不重复,这时候才不能用。

#25


自增字段在用DBEdit开发时,如果你调用了ADOTable.Append;方法后,该DBEdit上Text内容是不可见的(不能让用户立即看见新生成的流水号)。只有保存后POST才能看见。我想让它马上显示出新增的ID。另外本人用是access+ado是个单机的系统,求教好的方法!!!

#26


那你不能不用DBedit吗?怎么能怪到自增字段的头上呢?
其实什么DBedit,DBGrid之类的,会给你的开发带来很大的限制,想要方便,就必须放弃一定的*度,有得必有失。

#27


呵呵~~各位我已经想出来个办法了,可能比较蠢,但挺灵的,请各位指教。

//ID为ACCESS中的长整形字段,代表图书的唯一性代码

procedure TForm1.Button1Click(Sender: TObject);
var
  j,k: Integer;
begin
  ADOTable1.Sort:='ID ASC';
  ADOTable1.First;
  j:=ADOTable1['ID'];
  ADOTable1.Next;
  k:=ADOTable1['ID'];

  while (k-j=1) do
  begin
    j:=k;
    ADOTable1.Next;
    k:=ADOTable1['ID'];
  end;

  Edit1.Text:=Inttostr(j+1);

#28


可能我的办法有点笨了。呵呵~~~~~自动查找到不连续的那个ID的开始处,然后插入新的ID号。

#29


identity