線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:3047
推到 Plurk!
推到 Facebook!

寫一個生成永不重復的單號的函數?

答題得分者是:Justmade
hua2000
中階會員


發表:102
回覆:200
積分:65
註冊:2006-11-04

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-10-17 09:18:36 IP:218.20.xxx.xxx 未訂閱
請給一個能生成永不重復的單號的函數, 這個函數能生成一個單號,要求是單號的前兩位是edit1中的字串,在後的是當前日期,在在期後便是不重復的號碼。 最後能給出這個函數的源碼。 多謝! 胡 發表人 - hua2000 於 2002/11/07 20:02:34
wnhoo
高階會員


發表:75
回覆:443
積分:198
註冊:2003-04-22

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-05-02 08:45:49 IP:61.155.xxx.xxx 未訂閱
你可以这样实现: 2个EDIT1中字符+datettimetostr(当前的日期、时间)+不重复的字符代码    其中前2个都好实现,关键是第三个;我们可以取当前机器的MAC等方式地址 下面我给你个取MAC的函数。    function GetPhysicalAddress: string; Var   NCB : TNCB;   ADAPTER : TADAPTERSTATUS;   LANAENUM : TLANAENUM;   intIdx : Integer;   re : Char;   buf : String;   mm:string[20];    begin   Try     // Reset adapter     ZeroMemory(@NCB, SizeOf(NCB));     NCB.ncb_command := Chr(NCBRESET);     NCB.ncb_lana_num := LANAENUM.lana[0];//important     re := NetBios(@NCB);     If Ord(re)<>0 Then     begin       Result := '';       exit;     end;     // Get adapter address     ZeroMemory(@NCB, SizeOf(NCB));     NCB.ncb_command := Chr(NCBASTAT);     NCB.ncb_lana_num := LANAENUM.lana[0];////bowman     StrPCopy(NCB.ncb_callname, '*');     NCB.ncb_buffer := @ADAPTER.adapter_address[0];     NCB.ncb_length := SizeOf(ADAPTER);     re := NetBios(@NCB);     If Ord(re)<>0 Then       exit;     buf := '';     For intIdx := 0 To 5 Do       buf := buf + InttoHex(Integer(ADAPTER.adapter_address[intIdx]),2);       mm := copy(buf,0,length(buf));   finally   //  freemem(@NCB,SizeOf(NCB));    result:=mm; end; end;    风花雪月 e梦情缘
------
风花雪月 e梦情缘
cmj
高階會員


發表:15
回覆:242
積分:226
註冊:2002-06-12

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-05-04 00:00:19 IP:211.76.xxx.xxx 未訂閱
不重覆單號若不管資料庫的話,應該是以時間來產生.
Function LastNO(ss:String):string; //ss:輸入前置字串
begin
  Return:=ss FormatDateTime('yyyymmddhhnnss',Now);
end;
不過單號較長 14 前置字串長度.
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-05-04 11:30:15 IP:218.16.xxx.xxx 未訂閱
其實日期時間不一定要以標準的年月日時分秒來表達,直接以數值來處理可節省位數和加強精準度 例如以數值來表達 time 部份 : 可用 Format('%5.5d',[Round(Frac(Now) * 100000)]) 這樣就可節省一個位 (由六位變五位) 及使精準度提升到 0.86 秒 (每0.86秒數值加一)。 若想進一步提升精準度,可以加一位 : Format('%6.6d',[Round(Frac(Now) * 1000000)]); 這樣使用與hhnnss同一位數但精準度提升到 0.086 秒,重覆的機率比用 hhnnss 改善 11.6 偣。 若日期也可接受類似方法,可進一步淢少位數,用5 個位可使用27年 (如 2003 到 2030)若使用6 個位則可使用 270 年。但由於不能直接看出日期,所以使用 yymmdd (6 個位可使用 99 年)仍是不錯的選擇。 不過無論精準多高也是有可能重覆的,所以要安全的方法還是到數據庫伺服器取碼的好。
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-05-04 11:56:47 IP:218.32.xxx.xxx 未訂閱
除上面幾位前輩所提供的方法外, 如果是 MSSQL 或 Sybase 也可考慮運用 "Timestamp" 資料型別 : timestamp 是顯露自動產生的二位元數字的資料型別,它保證在資料庫中為唯一的。timestamp 通常用於版本戳記資料表資料列的機制。儲存大小為 8 位元組。 一個資料表只可以有一個 timestamp 資料行。每次插入或更新包含 timestamp 資料行的資料列時,便會更新 timestamp 資料行中的值。此特性使 timestamp 資料行不適合作為索引鍵,尤其是作為主索引鍵。任何對資料列的更新都會變更 timestamp 值,然後變更索引鍵值。
hua2000
中階會員


發表:102
回覆:200
積分:65
註冊:2006-11-04

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-05-05 11:44:59 IP:218.19.xxx.xxx 未訂閱
引言: 其實日期時間不一定要以標準的年月日時分秒來表達,直接以數值來處理可節省位數和加強精準度 例如以數值來表達 time 部份 : 可用 Format('%5.5d',[Round(Frac(Now) * 100000)]) 這樣就可節省一個位 (由六位變五位) 及使精準度提升到 0.86 秒 (每0.86秒數值加一)。 若想進一步提升精準度,可以加一位 : Format('%6.6d',[Round(Frac(Now) * 1000000)]); 這樣使用與hhnnss同一位數但精準度提升到 0.086 秒,重覆的機率比用 hhnnss 改善 11.6 偣。 若日期也可接受類似方法,可進一步淢少位數,用5 個位可使用27年 (如 2003 到 2030)若使用6 個位則可使用 270 年。但由於不能直接看出日期,所以使用 yymmdd (6 個位可使用 99 年)仍是不錯的選擇。 不過無論精準多高也是有可能重覆的,所以要安全的方法還是到數據庫伺服器取碼的好。
如果想得到永不重復的單號的話,如何向數據庫何去何從服器取碼并產生新號呀? 想通過一個按鈕”新單“來APPEND主從表數據的同時,產生一個不重復的單號顯示在dbtext1中。現在的我用的方法有點兒象Justmade上面的方法,但總是會有重復的機會的。且此一個程式是給好些人用的,好些人都要用它要開單且打印。 IMPROVE FOREVER
hua2000
中階會員


發表:102
回覆:200
積分:65
註冊:2006-11-04

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-05-05 11:47:41 IP:218.19.xxx.xxx 未訂閱
引言:
引言: 其實日期時間不一定要以標準的年月日時分秒來表達,直接以數值來處理可節省位數和加強精準度 例如以數值來表達 time 部份 : 可用 Format('%5.5d',[Round(Frac(Now) * 100000)]) 這樣就可節省一個位 (由六位變五位) 及使精準度提升到 0.86 秒 (每0.86秒數值加一)。 若想進一步提升精準度,可以加一位 : Format('%6.6d',[Round(Frac(Now) * 1000000)]); 這樣使用與hhnnss同一位數但精準度提升到 0.086 秒,重覆的機率比用 hhnnss 改善 11.6 偣。 若日期也可接受類似方法,可進一步淢少位數,用5 個位可使用27年 (如 2003 到 2030)若使用6 個位則可使用 270 年。但由於不能直接看出日期,所以使用 yymmdd (6 個位可使用 99 年)仍是不錯的選擇。 不過無論精準多高也是有可能重覆的,所以要安全的方法還是到數據庫伺服器取碼的好。
如果想得到永不重復的單號的話,如何向數據庫何去何從服器取碼并產生新號呀?能不能給我一些關鍵的代碼呀?(我通過Tadodataset來連接Tadoconnect來存入或獲取數據的) 想通過一個按鈕”新單“來APPEND主從表數據的同時,產生一個不重復的單號顯示在dbtext1中。現在的我用的方法有點兒象Justmade上面的方法,但總是會有重復的機會的。且此一個程式是給好些人用的,好些人都要用它要開單且打印。 IMPROVE FOREVER
IMPROVE FOREVER
hua2000
中階會員


發表:102
回覆:200
積分:65
註冊:2006-11-04

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-05-05 12:00:33 IP:218.19.xxx.xxx 未訂閱
引言: 除上面幾位前輩所提供的方法外, 如果是 MSSQL 或 Sybase 也可考慮運用 "Timestamp" 資料型別 : timestamp 是顯露自動產生的二位元數字的資料型別,它保證在資料庫中為唯一的。timestamp 通常用於版本戳記資料表資料列的機制。儲存大小為 8 位元組。 一個資料表只可以有一個 timestamp 資料行。每次插入或更新包含 timestamp 資料行的資料列時,便會更新 timestamp 資料行中的值。此特性使 timestamp 資料行不適合作為索引鍵,尤其是作為主索引鍵。任何對資料列的更新都會變更 timestamp 值,然後變更索引鍵值。
我試了一下這個timestamp,發現我設它為非空字段,不輸入任何數據,仍能向其它字段加入數據,真是好用,但我想查看其數據,為什麼看不到呀? 它能作為我的detail表中的detail表與主表的關聯字段嗎?(ORACLE有沒有這個特征呀?) IMPROVE FOREVER
Justmade
版主


發表:94
回覆:1934
積分:2030
註冊:2003-03-12

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-05-05 12:21:35 IP:218.16.xxx.xxx 未訂閱
可以在一個 Table 放 Counter, 要取碼時取出最大的數, 加一後更新進Table,(用 update tablename set counter = 10 where counter = 9) // 10,9 改成當時的值 若更新成功即沒別人同一時間取碼你便可以用那個碼 若更新失敗即有人剛取了碼,重做以上程序便可。
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-05-05 13:27:15 IP:218.163.xxx.xxx 未訂閱
Oracle 有類似的隱含欄位 ROWID, 節錄其說明文件 :    rowids,ROWID pseudocolumn and ROWID datatype    Every row in a nonclustered table of an Oracle database is assigned a unique rowid that corresponds to the physical address of a row’s row piece (or the initial row piece if the row is chained among multiple row pieces).    Each table in an Oracle database has an internal pseudo-column named ROWID. This pseudocolumn is not evident when listing the structure of a table by executing a SELECT statement, or a DESCRIBE statement using SQL*Plus, but can be retrieved with a SQL query using the reserved word ROWID as a column name.    rowids use a binary representation of the physical address for each row selected. A rowid’s VARCHAR2 hexadecimal representation is divided into three pieces: block.slot.file. Here, block is the data block within a file that contains the row, relative to its datafile; row is the row in the block; and file is the datafile that contains the row. A row’s assigned ROWID remains unchanged usually. Exceptions occur when the row is exported and imported (using the Import and Export utilities). When a row is deleted from a table (and the encompassing transaction is committed), the deleted row’s associated ROWID can be assigned to a row inserted in a subsequent transaction.    
cmj
高階會員


發表:15
回覆:242
積分:226
註冊:2002-06-12

發送簡訊給我
#11 引用回覆 回覆 發表時間:2003-05-05 22:43:25 IP:211.76.xxx.xxx 未訂閱
系統提供多人同時使用,在同時新增時如何自動產生不重覆單號,這應該是你的訴求,這是一個觀念問題.
我提供個人經驗參考看看.
1.假設單號格式YYYYMMDD999 西元年月日 3碼流水號如 20030501001
2.如何產生不重覆單號,應是在存檔前取輸入日期的最大單號加一,再存入這樣就
  不會有單號重覆問題,所以單號不是在新增帑存檔前知道,而是在存檔後才知道
3.若有主檔,明細檔結構,先新增存入主檔以產生單號也就是主檔已有記錄,再編
  輯明細檔.
4.至於單號可以是一個欄位 OR 分日期,序號兩個欄位.
longsanglin
初階會員


發表:10
回覆:57
積分:43
註冊:2002-04-23

發送簡訊給我
#12 引用回覆 回覆 發表時間:2003-05-06 10:30:10 IP:211.22.xxx.xxx 未訂閱
在Oracle中有利用Sequence Object來做流水號部份.前面在加上年月(YYYYMM)即可達到永不重複
hua2000
中階會員


發表:102
回覆:200
積分:65
註冊:2006-11-04

發送簡訊給我
#13 引用回覆 回覆 發表時間:2003-05-06 16:26:05 IP:218.20.xxx.xxx 未訂閱
我願準備把代碼復制過來的,但是代碼總是每一行跑到最左邊了,所以用圖片代替:         上面的那些代碼以前用的,但是我總感到它的速度太慢,且每次要CLOSE一次,再OPEN一次, 各位幫我看一下,要什麼地方改一下能使它的速度快一些,且能不能不要先CLOSE一次,再OPEN一次呀? 。。。。。。。。。。。 IMPROVE FOREVER
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#14 引用回覆 回覆 發表時間:2003-05-06 21:27:20 IP:218.32.xxx.xxx 未訂閱
呵呵...大家繞好大一圈...    1. 你 temp 取該計算機時間會有問題 , 改另外用一個 AdoDataSet2.commandtext :='select sysdate from dual' 取得 Oracle Server 的當時時間. 但如果主機時間往前調整(尤其是往前調整), 仍然會有問題 所以大家繞一圈是對的...哈哈
hua2000
中階會員


發表:102
回覆:200
積分:65
註冊:2006-11-04

發送簡訊給我
#15 引用回覆 回覆 發表時間:2003-05-07 09:19:39 IP:218.20.xxx.xxx 未訂閱
是不是一定要CLOSE,再OPEN Tdataset, 有沒有辦法能夠不用打開,關閉Tdataset呀,且能夠新增數據、產生新的單號呀?(上面的代碼) 每次都這樣速度好慢! 發表人 - hua2000 於 2003/05/07 09:20:41
wnhoo
高階會員


發表:75
回覆:443
積分:198
註冊:2003-04-22

發送簡訊給我
#16 引用回覆 回覆 發表時間:2003-05-10 07:52:58 IP:61.155.xxx.xxx 未訂閱
var I:double; isok:boolean; begin isok:=true; Randomize; while isok do begin try i:=round(Random*strtofloat(formatdatetime('yyyymmdd',now))); adodataset1.Edit ; adodataset1.Append ; adodataset1.FieldByName('bianhao').AsString :=floattostr(i)+FormatDateTime('YYYY:MM:DD_HH:MM',Now); adodataset1.Post ; isok:=false; except adodataset1.Cancel ; isok:=true; end;    end; end;    风花雪月 e梦情缘
------
风花雪月 e梦情缘
hua2000
中階會員


發表:102
回覆:200
積分:65
註冊:2006-11-04

發送簡訊給我
#17 引用回覆 回覆 發表時間:2003-05-10 10:05:15 IP:218.20.xxx.xxx 未訂閱
引言: var I:double; isok:boolean; begin isok:=true; Randomize; while isok do begin try i:=round(Random*strtofloat(formatdatetime('yyyymmdd',now))); adodataset1.Edit ; adodataset1.Append ; adodataset1.FieldByName('bianhao').AsString :=floattostr(i) FormatDateTime('YYYY:MM:DD_HH:MM',Now); adodataset1.Post ; isok:=false; except adodataset1.Cancel ; isok:=true; end; end; end; 风花雪月 e梦情缘
在網上也看了一些關于隨機數的例子,聽它們講,它的重復的機會好高的喲!
Terran_sigh
一般會員


發表:1
回覆:1
積分:0
註冊:2003-05-10

發送簡訊給我
#18 引用回覆 回覆 發表時間:2003-05-10 13:23:58 IP:219.154.xxx.xxx 未訂閱
在服务端写一个存贮过程 比如Table有 ID ,Field_1,Field_2 .... 生成的不重号可以这样写 declare @MaxID select @MaxID = max(ID) from Table set @MaxID = @MaxID 1 但这样对于CS的系统可能会重,因为大家可能同时取到MaxID 一样 所以可以先加入一行, INSERT INTO Table (ID) VALUES (@MaxID) 最后 result = @MaxID 返回
japhenchen
高階會員


發表:51
回覆:444
積分:184
註冊:2003-07-23

發送簡訊給我
#19 引用回覆 回覆 發表時間:2003-12-17 18:27:41 IP:211.96.xxx.xxx 未訂閱
我現在加入討論會不會太晚了點? 我以前的做法,將流水號存在另外一個table里記錄下來,每取回一個流水號,就幫他加1後存回去,所有的流水號都要用這步驟取回,在MSSQL2K中可以用STOREPROCEDURE來做這事簡化取存流水號的工作 現在的做法(反正我用慣了MSSQL),用自動編號欄位來處理第一個PK,第二個就記錄當時的時間(NOW * 86400000),這已經保証不重覆了~ 左邊的照片是我兒子哩
系統時間:2024-06-24 20:48:45
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!