全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:6612
推到 Plurk!
推到 Facebook!

一個觀念的問題,有關編號產生的方法

答題得分者是:P.D.
Phaeton0418
一般會員


發表:1
回覆:3
積分:0
註冊:2007-08-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-08-15 14:11:21 IP:220.228.xxx.xxx 訂閱
大家好,新人初來此,請大家多包涵。

我想產生一個訂單編號,編碼方式為民國年月日(Ex:0960815) 三位訂單碼 (EX:001)

也就是第一張訂單為0960815001 第二張為0960815002,關掉程式再開,還是會出現096081503 (因為還是8/15)

但如果隔天(8/16),打開程式時會自動變成0960816001

我是該在資料庫端做,還是在程式端先做好?希望高手能指點一下,不用程式碼全部給我,只希望給我觀念就好

麻煩大家了,謝謝。


Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-08-15 14:23:33 IP:211.22.xxx.xxx 未訂閱
最近寫多國語言程式正好寫了一個相同的函數,請參考~ <textarea cols="60" rows="10" class="delphi" name="code"> function TMaintanceCategoryTntForm.RetrieveID(Sender:TObject;TableName,FieldName:WideString):WideString; var aNumber:Integer; aID,aDate,aSQL:WideString; begin aDate := WideString(FormatDateTime( 'YYYYMMDD',Now)); try PTDataModule.PTADODataModule.PTADOConnection.Open; PTDataModule.PTADODataModule.AsistTntADOQuery.Close; PTDataModule.PTADODataModule.AsistTntADOQuery.SQL.Clear; PTDataModule.PTADODataModule.AsistTntADOQuery.SQL.Add( 'SELECT COUNT(*) AS Total FROM ' TableName ' WHERE 1=1' ); PTDataModule.PTADODataModule.AsistTntADOQuery.Open; aNumber := PTDataModule.PTADODataModule.AsistTntADOQuery.FieldByName('Total').AsInteger; if ( aNumber <= 0 ) then begin aID := WideString(Format('%s%.06d',[aDate,1])); end else begin aSQL := 'SELECT ' FieldName ' FROM ' TableName ' WHERE MID(' FieldName ',1,LEN(' aDate ')) =' aDate; PTDataModule.PTADODataModule.AsistTntADOQuery.Close; PTDataModule.PTADODataModule.AsistTntADOQuery.SQL.Clear; PTDataModule.PTADODataModule.AsistTntADOQuery.SQL.Add( aSQL ); PTDataModule.PTADODataModule.AsistTntADOQuery.Open; if ( PTDataModule.PTADODataModule.AsistTntADOQuery.RecordCount = 0 ) then begin aID := WideString(Format('%s%.06d',[aDate,1])); end else begin aSQL := 'SELECT MAX(MID(' FieldName ',Len(' aDate ') 1 )' ') AS MaxNumber FROM ' TableName ' WHERE MID(' FieldName ',1,Len(' aDate '))=' aDate; PTDataModule.PTADODataModule.AsistTntADOQuery.Close; PTDataModule.PTADODataModule.AsistTntADOQuery.SQL.Clear; PTDataModule.PTADODataModule.AsistTntADOQuery.SQL.Add( aSQL ); PTDataModule.PTADODataModule.AsistTntADOQuery.Open; aNumber := Integer(PTDataModule.PTADODataModule.AsistTntADOQuery.FieldValues['MaxNumber']) 1; aID := WideString(Format('%s%.06d', [ aDate , aNumber ] ) ); end; end; finally PTDataModule.PTADODataModule.PTADOConnection.Close; end; Result := aID; end; </textarea>
Phaeton0418
一般會員


發表:1
回覆:3
積分:0
註冊:2007-08-06

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-08-15 15:03:48 IP:220.228.xxx.xxx 訂閱
版主,非常感謝您的回應,不過您的程式碼我目前是有看沒有很懂,不曉得能口述一下這個編碼的觀念嗎?因為我不太了解Format %  那部分

我想了解一下概念,然後看自己能不能寫出來^^~ 但我非常感謝您的程式碼,感謝您無私的分享。
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-08-15 16:31:33 IP:61.67.xxx.xxx 未訂閱
你這應該無關於資料庫端或程式端的問題吧!
其實你應該是要做一個QUERY來查詢最後已用的單號,也就是當我要取號時,先透過QUERY查詢當天已開的最後一號,然後順序 1回傳值,如果變成明天查詢時,也是一樣查詢當天已開最後一號的動作,但我不知道你用何種資料,一般SQL的資料庫都會有提供
SELECT MAX(序號欄位) AS MAXSERNO FROM 資料庫 WHERE 我的條件=....
執行後只要讀取 MAXSERNO 值就是最大值
如果是使用DB檔等,不提供MAX()用法,則可以將資料庫以 FILTER過濾出當天的記錄,利用 ORDER BY 序號欄位 DESC 方式將資料由大到小排列,然後取第一筆就是最大值

當然這是一個作業基本概論,當中還有多必須考量的狀況要去處理,就不在本題中論述(如多人共共,鎖定問題....)
Phaeton0418
一般會員


發表:1
回覆:3
積分:0
註冊:2007-08-06

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-08-15 17:46:58 IP:220.228.xxx.xxx 訂閱
P.D版主您好! 您說的是方法可能沒有考慮到我想要的編碼 【民國年月日 + 單號】  假設db裡有001 、 002 這要查詢後取出 +1 這個ok,

但是有關於到前面要加民國年月日,這邊我的問題比較大,以及第一筆資料! 如果我是先抓資料庫裡的001出來重新編碼再update,還是

直接就編 比如 0960815001 然後寫入db?那如果這樣,隔了一天 我是先做文字比較,再決定單號是要 1下去,還是從001開始 !這是我目前

想到的方法,但我覺得好像沒有很好,希望能聽聽其它高手的意見。 也感謝PD版主的回答,謝謝您抽空回應。
pedro
尊榮會員


發表:152
回覆:1187
積分:892
註冊:2002-06-12

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-08-15 20:13:19 IP:61.231.xxx.xxx 未訂閱
可開一資料表取單號設定取單號規則
單據日期名稱,編號位數,目前編號,每次累進
例如:
Order20070810,4,12,1(8/10這天訂單單據號碼已用到12號,200708100012,下次會編成200708100013)
Return20070512,4,7,1 (5/12這天退貨單據號碼已用到7號,200705120007,下次會編成200705120008)
每次取號完會update當天編號檔的目前編號
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-08-15 23:53:40 IP:61.67.xxx.xxx 未訂閱
你要的這種編排法,用的最多的就是會計憑證取號功能,如果你利用我說的方法,在當天如果找不到記錄,代表當天沒有開過號,當然就從001開始,其實你誤解我的意思了,我並不是說單號用001, 002 來排,天下沒有這種白痴排法,我講的是今天
0960815001, 0960815002. 0960815003...., 明天就0960816001, 0960816002... ,這樣絕對可以取出最大號的
編輯記錄
P.D. 重新編輯於 2007-08-15 23:54:30, 註解 無‧
g9221712
高階會員


發表:145
回覆:344
積分:162
註冊:2006-07-06

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-08-16 03:07:03 IP:220.132.xxx.xxx 訂閱
Stallion 前輩:

我想再請叫一個額外的問題,是否可以煩請您給予觀念指正!
一般編號產生,都會使用計算的方式,然後寫入主子單據,目前我也是這樣作,但是很怕一些特殊情形,就是若是多機連線作業取單號,
若是遇到前一個單號已經取走(如20070816001),而下一個使用者又取得新的單號(如20070816002),而(如20070816001)因作業需求
取消這張單據,不知道一般的作法是否會產生跳號,而單據編號的取得,到底是應該採打單時立即取單號(可以簡化主子單據Link的撰寫)
,還是存檔時才將暫存單號改以計算的單號來代替(可以避免單據編號跳號)?真是困擾啊?

------
「人們所以覺得寂寞,是因為他們會築牆,卻不會搭橋。」
程式寫的越久,卻發現自己越來越不會寫程式!
eaglewolf
資深會員


發表:4
回覆:268
積分:429
註冊:2006-07-06

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-08-16 09:02:31 IP:211.75.xxx.xxx 訂閱
個人覺得這沒有一定的準則
完全看企業體允不允許跳號
如果允許那自然是最簡單的
如果不允許
可先以臨時編號顯示等到確認後再提示使用者正式編號
或者顯示正式編號等到確認後若有變更編號再提示使用者變更後的編號

------
先查HELP
再查GOOGLE
最後才發問

沒人有義務替你解答問題
在標題或文章中標明很急
並不會增加網友回答速度

Developing Tool:
1.Delphi 6
2.Visual Studio 2005
3.Visual Studio 2008
DBMS:
MS-SQL
Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2007-08-16 09:39:47 IP:211.22.xxx.xxx 未訂閱
這個問題我是這樣避免的!
上面的寫法我是因為寫給個人使用所以利用MDB操作資料庫時沒有使用交易。
正常多人狀況下,應該是在客戶端將所有數據填妥後按下「新增」或「修改」時,先將資料庫作交易的動作暫時鎖住資料庫,然後將要號資料儲存一口氣做完,就不至於發生你說的情形。
另外,如果號碼要重用,要作的是情就是增加一個子表,把刪除後的號碼放在這裡,於新增要號時,在交易中先看看這裡有無舊號可用而已。
===================引 用 g9221712 文 章===================
Stallion 前輩:

我想再請叫一個額外的問題,是否可以煩請您給予觀念指正!
一般編號產生,都會使用計算的方式,然後寫入主子單據,目前我也是這樣作,但是很怕一些特殊情形,就是若是多機連線作業取單號,
若是遇到前一個單號已經取走(如20070816001),而下一個使用者又取得新的單號(如20070816002),而(如20070816001)因作業需求
取消這張單據,不知道一般的作法是否會產生跳號,而單據編號的取得,到底是應該採打單時立即取單號(可以簡化主子單據Link的撰寫)
,還是存檔時才將暫存單號改以計算的單號來代替(可以避免單據編號跳號)?真是困擾啊?

Phaeton0418
一般會員


發表:1
回覆:3
積分:0
註冊:2007-08-06

發送簡訊給我
#11 引用回覆 回覆 發表時間:2007-08-16 11:15:39 IP:220.228.xxx.xxx 訂閱
ST版大,PD版大以及Pedro前輩還有參與這個主題的所有人,感謝大家。經過這些前輩的指導,我已經了解我該怎麼做了!謝謝PD版大一再講解,很抱歉讓您這樣一再重覆講解 (我還誤會意思> <) , 謝謝謝謝。 以下是題外話:

1、有位前輩在這主題裡有提額外的問題,請這位前輩如果得到滿意的答案後,要回一下版,因為我不了解會不會我【結案】後您就無法使用這個主題了。

2、好像結案後會有個得分,但講真的,大家都有幫上忙,結案得分只能給一人嗎?因為我怕一按下結案就要決定。想先問一下,謝謝大家。
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#12 引用回覆 回覆 發表時間:2007-08-16 17:05:16 IP:61.67.xxx.xxx 未訂閱
1.結案只是一個給分作業,代表本案已獲得滿意答覆,但不代表未來不會有更好的方法,所以結案後還是可以繼續討論,不過結案之後原發問人要提問,請另外再開一個版面,而我指可以繼續討論的動作是說,如果其他網友針對這個問題有更精擘的見解時,他可以在結案後繼續加入此項討論,而不是讓原發問題一個問題接一個問題的問下去,請不要誤解!
2.給誰,對我們來說或許不是那麼重要,拿到了這個分數我們又不會獲得額外的報酬,除非站長願意開放一個付費討論,依據得分狀況我們回答問題能有所報酬(站長大人不好意思哦! 說笑話啦), 只是我們希望,因為我們也是這樣走過來的,所以也希望大家在程度上不斷昇等時,也能為本站做一些付出是比較正面的看法!
sryang
尊榮會員


發表:39
回覆:762
積分:920
註冊:2002-06-27

發送簡訊給我
#13 引用回覆 回覆 發表時間:2007-09-03 12:59:34 IP:59.125.xxx.xxx 訂閱
個人提供一種方法供參考
http://delphi.ktop.com.tw/board.php?cid=30&fid=66&tid=66683
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/
qqqufo
一般會員


發表:1
回覆:17
積分:8
註冊:2007-06-01

發送簡訊給我
#14 引用回覆 回覆 發表時間:2007-09-24 17:15:38 IP:218.85.xxx.xxx 訂閱
我觉得这个不应产生在程序当中。
对于单号的生成,有两种方案,一种是用序号,从001开始,一种是日期加序号,如 0960815001这种,但这种文案存在一定的局限,那就是如果当天的单据多于1000单,这个编号就不适用了。
略过不表,谈一下如何生成这个序号

1.这个序号应该由数据库生成,因为只有数据库才能准确知道当前哪个序号是可用的,程序有一定时限性,如,程序当如 Stallion 所示时。客户端A程序取得一个序号 0960815001 ,尚未写入数据库之前,另一个客户端B也可能取得这个序号,此时A写入数据库,B也写入数据库,于是,出现单据号重复而提交失败!
2.正确的文法是在GUI界面中不显示单据号,提交时也不提交单据号的列,在提交时由数据库的触发器往此记录中填入单据号,此时数据库可以保证此单据号是唯一的。
3.在某些数据库中,单据号是可由数据库代码获得的,如,在Oracle中,可以这样写插入语句

Inset into 进货单据(单据ID,供货商) values (SEQ_IN.Nextval,"假定供货商"),这样可以产生一个不重复的序数单据号,但此时的单据号是连接的001,002之类的。只要在提交变更前检查一下有没有今天(0960815)开头的单据,如果没有,就重建 SEQ_IN,使之从1开始,若有,则直接使用即可。
4.如果需要将单据号显示在GUI中,则可以在界面显示时,或按下新增按钮时从序号 SEQ_IN中取得 nextval ,显示出来,然后写入,如果这个单据没有保存,则并序号不可再用,出现断号。
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#15 引用回覆 回覆 發表時間:2007-09-25 17:27:16 IP:61.67.xxx.xxx 未訂閱
其實任何取用單號的方法都是有風險性的,要做出一個確保完整不重覆的取號流程真的十分困難,如果今天是完全單機運作考量或許大家提到的方法都是可行的,但如果一旦出現在網路行徑上時,要考慮的問題就非常多,不論是否由資料庫來產生或由各種資料來源來判斷都是一樣的! 固然由數據庫拉序號是比較安全的做法,但在台灣地區例如會計傳票等等,其實業主都十分注意序號的連續性,由資料庫取號是很容易造成序號的斷號或者取號者先進後進關係,很可能造成序號順序不正常,雖然是不重覆,但有可能變成 002,001 的順序,這也是我們所遇到的難題處,我沒有用過Oracle,並不清楚它的sequ產生方式是不是會解決斷號問題,但我想如果一套系統要提供十數人到數十人共用使用的話,取號的確是一個很難的平衡點,如果不在GUI提交單號的話,那在回存資料庫交由系統產生,在一個數十人同時上線使用的話,會造成取號上的時間差而失誤的比例可能會蠻高的,我的做法是讓每一台電腦都是獨立開號,但每一台電腦都有一個自己的獨立機號(3碼),所以透過一些分析公式,可以確保每一台取出的號碼是唯一性的,就算與他台取得同一號也沒有關係,因為有加上機號識別,另外一種做法是分配單號,每一台可用的序號範圍先設定好,這樣也可以保證每一台不會取到他台的編號範圍,當然這是要與業主溝通過,如果業主不能接受的話那還是沒輒!
ntjrr
高階會員


發表:240
回覆:312
積分:110
註冊:2005-04-24

發送簡訊給我
#16 引用回覆 回覆 發表時間:2007-09-25 19:54:06 IP:222.184.xxx.xxx 訂閱
这个问题其实比较经典,我也来说两句。如果只用序号,那么所有的问题都能解决好。但日期加序号的方式就比较难做。很容易产生重号或者跳号的问题。我目前是这样做的,也不知道对不对,运行是可以运行的,也暂时没测到错误。
肯定要用事务,窗口中肯定不好先写好号码,只能在新增时得到。但这里面遇到一个问题,就是新增时事务开始时先做什么?如果先查询日期,没有的话就是当前日期 001为所要的号码,有的话就是最大号加1为所要的号码,但这两个动作都是同一个问题,要先查询,也就意味着在事务中同样可能读到相同的数据,我是这样解决的:
ADOConnection1.BeginTrans
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'Insert Into tb_gh (单据号...........)'
' Values (:单据号,:.......)';
ADOQuery2//,注意是另一个adoquery,从这个位置开始执行日期查询得到日期加序号组成的单据号)
ADOQuery1.Parameters.ParamValues['单据号']:= 从上面查询得来的值
ADOQuery1.execsql;

我是把ADOQuery2的查询夹在了adouquery1 insert 之后,但又在excesql 之前,不知道这样是否就控制住了取到同号,又能防止跳号了。
------
我的编程起步于ktop,我将永远支持ktop
qqqufo
一般會員


發表:1
回覆:17
積分:8
註冊:2007-06-01

發送簡訊給我
#17 引用回覆 回覆 發表時間:2007-09-26 13:15:04 IP:218.85.xxx.xxx 訂閱

===================引 用 P.D. 文 章===================
其實任何取用單號的方法都是有風險性的,要做出一個確保完整不重覆的取號流程真的十分困難,如果今天是完全單機運作考量或許大家提到的方法都是可行的,但如果一旦出現在網路行徑上時,要考慮的問題就非常多,不論是否由資料庫來產生或由各種資料來源來判斷都是一樣的! 固然由數據庫拉序號是比較安全的做法,但在台灣地區例如會計傳票等等,其實業主都十分注意序號的連續性,由資料庫取號是很容易造成序號的斷號或者取號者先進後進關係,很可能造成序號順序不正常,雖然是不重覆,但有可能變成 002,001 的順序,這也是我們所遇到的難題處,我沒有用過Oracle,並不清楚它的sequ產生方式是不是會解決斷號問題,但我想如果一套系統要提供十數人到數十人共用使用的話,取號的確是一個很難的平衡點,如果不在GUI提交單號的話,那在回存資料庫交由系統產生,在一個數十人同時上線使用的話,會造成取號上的時間差而失誤的比例可能會蠻高的,我的做法是讓每一台電腦都是獨立開號,但每一台電腦都有一個自己的獨立機號(3碼),所以透過一些分析公式,可以確保每一台取出的號碼是唯一性的,就算與他台取得同一號也沒有關係,因為有加上機號識別,另外一種做法是分配單號,每一台可用的序號範圍先設定好,這樣也可以保證每一台不會取到他台的編號範圍,當然這是要與業主溝通過,如果業主不能接受的話那還是沒輒!



PD版主描述的这种情况,每台机器配置一个机器识别码,会增加码长使得编码更长串,另外,如果程序设计的时候使用的是MDI的话,同样可能因为用户同时打开两个同样的窗口(假设允许同时打开两个相同功能的窗口并进行新增)的话,同样可能因为保存的时间不一致,或者先开的那张单据并不保存而导致序号错乱或断号。除非给定一个条件,一个功能一个时间只能开一个窗口。
其次,加机器号的编码也是不连续的。如 日期 机器编号 序号 0960815001001 0960815001002 0960815088001 三个单据号,前两个有序号关系,但前两个与第三个没有任何的序号关系,客户不一定能接受这种方式。
我沒有用過Oracle,並不清楚它的sequ產生方式是不是會解決斷號問題

Oracle 的序号 sequ 并不能解决断号问题,他只是一个序列号发生器,每向他请求一次,他负责给定一个序号,这个序号保证不重复,而且是连续的,关键是,如果某客户端从序号列中取出一个序号, 假设是 0960815001 ,那第,第二个向他请求序号的客户端,得到的序号就是 0960815002 ,不管第一个客户端拿到这个序号之后有没有使用这个序号,所填充的这张单据是保存提交到了数据库里还是根本就没有保存,放弃了所做的更改。正是因为如此,一个序列号发生器可以保证没有重复号码,但不可能保证序号的连续性。

如果不在GUI提交單號的話,那在回存資料庫交由系統產生,在一個數十人同時上線使用的話,會造成取號上的時間差而失誤的比例可能會蠻高的

此处的“时间失误”指的是新增单据的时刻还是保存单据的时刻呢,如果是指新增单据的时刻,那么,如果这个用户新增此单据,拿走一个序号却不使用呢,比如说,新增一张凭证,但不填写任何内容而退出,因为他仅仅是点错了而已?这样一定会造成“断号”

如果指的是“保存”,也就是“提交资料到数据库”时,那么,按照此时提交到数据库的顺序,序列号发生器会按顺序产生一个连续的,不重复的序号,数据库管理程序本身可以保证这个序号是连续的并且不重复的。而不管客户端使用者是10人或是35人,也不管一秒钟内提交了20笔数据或是196笔。

,另外一種做法是分配單號,

这种分配方案肯定会产生断号,除非号码方案是预先确定的,比如说规定财务科,本月所有的物质报损都只能做在一张凭证上,那么,无话可说。
还有一种不是办法的办法,那就是,定义一个计划任务,在每天的业务比较闲的时候,按照一定的规则(如提交时间,提交类型)重新整理序号,然后修改初始的单据号。这样可以保证单据号连续并且不重复,不过,单据号可不是随便都能改的。
综上所述,我仍然认为,提交资料到数据库,然后由数据库的序列号发生器产生序号,是最可靠的办法。
編輯記錄
qqqufo 重新編輯於 2007-09-26 13:16:21, 註解 無‧
qqqufo
一般會員


發表:1
回覆:17
積分:8
註冊:2007-06-01

發送簡訊給我
#18 引用回覆 回覆 發表時間:2007-09-26 13:42:01 IP:218.85.xxx.xxx 訂閱

===================引 用 ntjrr 文 章===================
这个问题其实比较经典,我也来说两句。如果只用序号,那么所有的问题都能解决好。但日期加序号的方式就比较难做。很容易产生重号或者跳号的问题。我目前是这样做的,也不知道对不对,运行是可以运行的,也暂时没测到错误。
肯定要用事务,窗口中肯定不好先写好号码,只能在新增时得到。但这里面遇到一个问题,就是新增时事务开始时先做什么?如果先查询日期,没有的话就是当前日期 001为所要的号码,有的话就是最大号加1为所要的号码,但这两个动作都是同一个问题,要先查询,也就意味着在事务中同样可能读到相同的数据,我是这样解决的:
ADOConnection1.BeginTrans
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'Insert Into tb_gh (单据号...........)'
' Values (:单据号,:.......)';
ADOQuery2//,注意是另一个adoquery,从这个位置开始执行日期查询得到日期加序号组成的单据号)
ADOQuery1.Parameters.ParamValues['单据号']:= 从上面查询得来的值
ADOQuery1.execsql;

我是把ADOQuery2的查询夹在了adouquery1 insert 之后,但又在excesql 之前,不知道这样是否就控制住了取到同号,又能防止跳号了。

不管在前还是在后,总之需要时间,在这段时间之内,就有另外一个人拿走了一个号码,并且,不使用,于是,又断号了。
ntjrr
高階會員


發表:240
回覆:312
積分:110
註冊:2005-04-24

發送簡訊給我
#19 引用回覆 回覆 發表時間:2007-09-26 15:09:57 IP:222.184.xxx.xxx 訂閱
不管在前还是在后,总之需要时间,在这段时间之内,就有另外一个人拿走了一个号码,并且,不使用,于是,又断号了。


这个应该是错误的想法,事务开始时就是锁住了,这个事务不结束,其它事务是不好开始的,他到哪里拿号码去呢?也就是写入数据,拿号,只有一个客户端可以进行,其它的是不能同时进行的。
------
我的编程起步于ktop,我将永远支持ktop
qqqufo
一般會員


發表:1
回覆:17
積分:8
註冊:2007-06-01

發送簡訊給我
#20 引用回覆 回覆 發表時間:2007-09-26 22:37:50 IP:125.77.xxx.xxx 訂閱

===================引 用 ntjrr 文 章===================
不管在前还是在后,总之需要时间,在这段时间之内,就有另外一个人拿走了一个号码,并且,不使用,于是,又断号了。


这个应该是错误的想法,事务开始时就是锁住了,这个事务不结束,其它事务是不好开始的,他到哪里拿号码去呢?也就是写入数据,拿号,只有一个客户端可以进行,其它的是不能同时进行的。

我很长时间不使用ADO,以下回复可能有错:

有ADO开始事务的时候,的确,需要提交整个的事务才行,但是,这个锁锁住的不是表,而是整串的数据指令,也就是说,在开始事务的时候,仍然有其他的用户可以访问这些数据,因为并没有锁。也就是说,用事务控制只能控制到本机代码的执行服务器却不会只处理一个事务,他会同时穿叉执行好几个事务的。
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#21 引用回覆 回覆 發表時間:2007-09-26 23:10:27 IP:61.67.xxx.xxx 未訂閱
一般鎖定事件對於新增的(APPEND)的事件是很難控制的,如果是Delete或Edit 還可以鎖定,而且就算可以在一個進入點後即鎖定整個資料庫,其他人都不能取得控制權的話,無疑是一個單機的運作,這就是我所說的,在一個單機作業下是很容易控制,但如果是多人要同時開單時就完蛋了,就如一般的賣場不可能只有一台電腦在收銀,也不可能讓一台收銀佔住整個資料庫要等這台結完帳才能其他台繼續結帳吧,所以,如果只是單台作業那基本上沒有什麼好討論,本篇中的任何做法都是ok的,重點是在於多人同時開單時,如何取號不重覆這才是一個很棘手的問題!
===================引 用 ntjrr 文 章===================
不管在前还是在后,总之需要时间,在这段时间之内,就有另外一个人拿走了一个号码,并且,不使用,于是,又断号了。


这个应该是错误的想法,事务开始时就是锁住了,这个事务不结束,其它事务是不好开始的,他到哪里拿号码去呢?也就是写入数据,拿号,只有一个客户端可以进行,其它的是不能同时进行的。
ntjrr
高階會員


發表:240
回覆:312
積分:110
註冊:2005-04-24

發送簡訊給我
#22 引用回覆 回覆 發表時間:2007-09-27 07:54:21 IP:222.184.xxx.xxx 訂閱
同时进行很多事务是有可能的,但前提就是事务封锁的表不同,事务A对表A在操作,事务B对表B在操作,那再多的事务也在同时。 事务同时进行时有些事务好访问也对的。但这里的访问不含修改,新增动作吧?事务进行时的顺序很重要,一开始就先查询,再写入,那么两个事务一起查询到相同的数据了,一个写好,再等另一个写。同样要出错。但如果事务中先写入后查询,那么,两个事务不可以同时进行的,非得等一个事务写入好,并且还要查询好后,另一个事务才好开始。

另外上面所说的只能一个事务进行,并不等同于单机操作,你哪怕多台电脑同时发出指令,同时要去取号,理论上有可能在数秒内所有的事务都处理好的,用户并没有什么感觉。

说的对与不对,请高手指正。
------
我的编程起步于ktop,我将永远支持ktop
編輯記錄
ntjrr 重新編輯於 2007-09-27 07:56:30, 註解 無‧
ntjrr 重新編輯於 2007-09-27 07:57:01, 註解 無‧
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#23 引用回覆 回覆 發表時間:2007-09-27 17:12:26 IP:61.67.xxx.xxx 未訂閱
或許我的說法讓樓上誤解了,只有查詢當然沒有問題,再多人進來也都可以應付自如,或者A-PC對A表,B-PC對B表那也是一對一的作業,對於取號並沒有困擾,我的意思是當A,B,C,D,E,F 同時對 A 表進行"存取"單號時,想想看這時A要如何發出5組不重覆的單號而且在存檔後仍能確保正確及不斷號!
ntjrr
高階會員


發表:240
回覆:312
積分:110
註冊:2005-04-24

發送簡訊給我
#24 引用回覆 回覆 發表時間:2007-09-27 21:25:04 IP:222.184.xxx.xxx 訂閱
不是误解的,我也是说的这个意思,A,B,C,D,E,F 同時對 A 表進行"存取"單號時,想想看這時A要如何發出5組不重覆的單號而且在存檔後仍能確保正確及不斷號! 这是可以做到的。
我们就不说日期加序号复杂的,说序号一个。只取序号,那么随意建一个数字段,叫pjh好了,事务开始,先update pjh:=pjh 1 然后 select pjh 那么取出的这个值就绝对不会重复或者断号的。 但如果是 先select pjh 再update pjh:=pjh 1那么就会要取到相同的票据号了。
依据的理由就是U锁要在事务结束时另一个事务才好再加U锁。 如果五台同时取,数据库估计在几秒内就同时处理好了吧,用户不会有什么慢的感觉。
当然不对之处请各位前辈指出,我也只是感觉应该对,但不说绝对是正确,否则我也不会在论坛上写出来,写出来就是为了得到更多的指点,让自己有更深的认识。
===================引 用 P.D. 文 章===================
或許我的說法讓樓上誤解了,只有查詢當然沒有問題,再多人進來也都可以應付自如,或者A-PC對A表,B-PC對B表那也是一對一的作業,對於取號並沒有困擾,我的意思是當A,B,C,D,E,F 同時對 A 表進行"存取"單號時,想想看這時A要如何發出5組不重覆的單號而且在存檔後仍能確保正確及不斷號!
------
我的编程起步于ktop,我将永远支持ktop
系統時間:2024-04-24 16:26:21
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!