想使用delphi自动生成“年后两位+月份+四位编号”的流水号
现新增第一条记录的时候能生成
第二条的时候流水号的最后一位就没了
大家帮忙看看我的代码错在哪里
  
procedure TForm1.FormCreate(Sender: TObject);
var
  i:Real;
  newid:string;
begin
  with ADOQuery1 do
     begin
        Close;
        SQL.Clear;
        SQL.Add(' select * from JYBB where id like '+''''+FormatDateTime('YYMM',Now())+'%'+'''');
        Open;
        if ADOQuery1.IsEmpty then
           newid:=formatdatetime('YYMM',Now())+'0001'
        else
           begin
            Close;
            SQL.Clear;
            SQL.Add('select max(id)+1 as i from JYBB where left(id,4)='''+FormatDateTime('YYMM',Now())+'''') ;
            Open;
            newid:=FormatDateTime('YYMM',Now())+ FormatFloat('000',i);
           end;
         Edit3.Text:=newid;
     end;
end; 

解决方案 »

  1.   

    FormatFloat('0000',i);
      

  2.   

    FormatFloat('0000',ADOQuery1.FieldByName('i').asInterger); 
      

  3.   

    FormatFloat('0000',ADOQuery1.FieldByName('i').asInteger); 
      

  4.   

    FormatFloat('0000',ADOQuery1.FieldByName('i').asInterger);
    也会不行的如果i是09100001,那么这个结果将会是9100001,再加上YYMM,最后是09109100001newid:=FormatDateTime('YYMM',Date)+ Copy(ADOQuery1.FieldValues['i'],5,4);
      

  5.   

    showmessage(ADOQuery1.FieldByName('i').asstring);//看一下可有值?SQL.Add('select max(id)+1 as i from JYBB where left(id,4)='''+FormatDateTime('YYMM',Now())+'''') ;
    改为
    SQL.Add(' select max(id)+1 as i from JYBB where id like '+''''+FormatDateTime('YYMM',Now())+'%'+'''');
      

  6.   

    这样生成编号 后期数据量稍大点的时候效率好像很有问题阿where 后面还有函数
      

  7.   

    能冒昧的问一句这是用的什么数据库吗?
    感觉你产生的流水号与实现语音无关,就是用的数据库的操作实现的我不写DELPHI,刚没事来看看
      

  8.   

    最好在一个sql里直接完成,否则多个客户端时,容易出错:
    declare @id int
    declare @ym varchar(20)
    select @ym=getdate()转为yyyymmdd格式后的3-6位
    select @id=isnull(max(right(id,4)),0) from tb where id like @ym+'%'
    set @id=@id+1
    insert tb (id) values (@ym+right('0000'+@id,4))
    select @id --返回新的id给客户端,以便补充其他字段
      

  9.   


      你FORMAT字符串有问题,自己写个填充函数比如
      /*============================
      piLength  --填充后的字符串长度
      psString  --被填充的字符串
      psFillString  --用该字符进行填充
      返回值: 填充后的字符串
      MagicYang   2009-10-24
      =============================*/
      function FillLeftString(piLength: integer;psString,psFillString: String): string;
      var 
        iTmp: integer;
        sTmp: string;
      begin
        result := '';
        if Length(psString) >=piLength then
          Exit;
        for i:=0 to piLength-Length(psString) do
          sTmp := psFillString+sTmp;
        result := sTmp;
      end; 
      

  10.   

    你数据库设计的有点不效率,每次你打开数据表都要like,并且还要用max函数取最大值,这样数据多了性能会下降的(当然,如果你最多也就几万条,那就无所谓了)
    并且,如果有并发处理,这样合成的顺序好不能保证是唯一的。
    建议你再创建一个表,这个表就两个字段,一个是记录 yymm 的,一个是记录当前顺序号最大值的,例如
    0910 0003
    0909 0039
    ......
    上面表示09年10月份当前最大编号是3,09年9月份当前最大编号是39,当然,如果你仅仅处理当前数据(没有对历史数据的新增问题),那么只要一条记录就足够了,就记录当前年月的最大号。
    然后你的程序中单独写一个函数用来获得指定年月的最大值,这个函数传入要查找的年和月,返回这个年月的最大值+1,在函数内部,采用select for update的方式打开表(写锁定的方式打开表),或者值之后,再+1,然后提交给数据库并关闭表(释放锁)。
    这样能保证你的序列号是唯一的,并且能保证你的号码是正确的。
    这样设计后,你在打开数据表的时候,仅仅使用 select * from JYBB where id > #39 + FormatDateTime('yymm', now()) + '0000' + #39就可以了,这样打开表,如果你在id上建立了索引,是非常快的。也省去了你再次用max的方式打开表。
    比如,你获得最大值的函数是getMaxNum(),则,需要最大号的时候,调用下就可以了newid := getMaxNum(FormatDateTime('yymm', now()));(当然了,上面的调用方式也意味着你的getMaxNum函数里面要把传入的年和月接到最大编号上返回,呵呵)
      

  11.   

    以下是我写的:看看有没有什么帮助procedure TForm1.Button5Click(Sender: TObject);  //新增
    var
    i,tnum:integer;
    t,t1,t2,t3:string;
    Year,Month,Day:WORD;
    begin
    if messagedlg('确认添加新记录吗?',mtconfirmation,[mbYes,mbNo],0)=mrYes then
    begin
      DecodeDate(Now,Year,Month,Day);
      t1:=inttostr(month);
      tnum:=month;
      with adoquery1 do begin
        close;
        sql.Clear;
        sql.Add('select * from T_dropdownexp order by no asc');
        open;
      for i:=0 to 26 do begin                                 //新增标题
        stringgrid1.Cells[i,0]:=adoquery1.Fields[i].FieldName;
      end;
      end;
      if tnum<10 then begin                         //判断月份是否为个位数,加0补齐两位数
        t1:='0'+t1;
        end;
      t2:=inttostr(year);
      if adoquery1.IsEmpty then
      stringgrid1.Cells[0,1]:=t2+t1+'0001'          //如记录为空,记录从1开始
      else
      with adoquery1 do begin
        close;
        sql.Clear;
        sql.Add('select * from T_dropdownexp order by no asc');
        open;
      adoquery1.Last;
      t:=adoquery1.Fields[0].AsVariant;
      t3:=copy(t,5,2);                              //在NO中取两位数为月份
      if t1<>t3 then                                //判断月份,相同则累计,不同则重新计
         stringgrid1.Cells[0,1]:=t2+t1+'0001'
      else
      stringgrid1.Cells[0,1]:=inttostr(strtoint(t)+1);
      end;
      stringgrid1.Cells[1,1]:=edit2.text;                     //新增输入内容
      stringgrid1.Cells[2,1]:=edit3.text;
      stringgrid1.Cells[3,1]:=edit4.text;
      stringgrid1.Cells[4,1]:=edit5.text;
      stringgrid1.Cells[5,1]:=edit6.text;
      stringgrid1.Cells[6,1]:=edit7.text;
      stringgrid1.Cells[7,1]:=edit8.text;
      stringgrid1.Cells[8,1]:=edit9.text;
      stringgrid1.Cells[9,1]:=edit10.text;
      stringgrid1.Cells[10,1]:=edit11.text;
      stringgrid1.Cells[11,1]:=edit12.text;
      stringgrid1.Cells[12,1]:=edit13.text;
      stringgrid1.Cells[13,1]:=edit14.text;
      stringgrid1.Cells[14,1]:=edit15.text;
      stringgrid1.Cells[15,1]:=edit16.Text;
      stringgrid1.Cells[16,1]:=memo4.Text;
      stringgrid1.Cells[17,1]:=edit22.Text;
      stringgrid1.Cells[18,1]:=memo5.Text;
      stringgrid1.Cells[19,1]:=edit23.Text;
      stringgrid1.Cells[20,1]:=memo6.Text;
      stringgrid1.Cells[21,1]:=combobox1.Text;
      stringgrid1.Cells[22,1]:=combobox2.Text;
      stringgrid1.Cells[23,1]:=combobox3.Text;
    end;
    end;
      

  12.   

    你這樣寫如果多客戶端同時進行連接操作的時候就容易產生同號了。
    我以前接觸過的是把目前的流水號(就後面五位,不包括年月日)保存在數據庫的一個表裏面,這個表裏面存放了所有表(需要有流水號)的流水號情況。
    每次要產生流水號的時候就從這個表裏面來取,用SQL函數來調用,這樣速度也快,而且也不太容易會出現同號的情況