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

使用主鍵(integer)自動產生,是好是壞?

答題得分者是:danny
pedro
尊榮會員


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

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-08-02 09:23:25 IP:60.248.xxx.xxx 未訂閱
小弟在實作三層,SA覺得開自動編號對SQL Server效能及空間比較節省
但我Client在新增一筆資料時,自動編號欄位無法帶到前端來,
於是搜尋一下網路資料,發現大陸網友發表一篇
http://www.wangwa.com/info/2006-07/7.htm

講三層架構裡,Sql自動編號欄位不適合用

請問有無前輩開發三層的,主鍵是否有用到Integer自動編號成功過?
特別是那種MasterDetail單據....
謝謝指導

編輯記錄
 重新編輯於 2007-08-02 09:35:29, 註解 使用主鍵(integer)自動產生,是好是壞?‧
danny
版主


發表:100
回覆:522
積分:595
註冊:2002-03-11

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-08-02 10:32:43 IP:203.79.xxx.xxx 訂閱
他不是指出重點了嗎 ? 
Master/Detail 因為 Detail 的 Key 必須與 Master 一樣, 而 "自動編號欄位" 必須要 post 後才知道, 那 Detail 在輸入時必無法得知(除非Master 先 post)
不過 Client 端如果只是輸入資料, 在 AP Server 那層也是可以使用的, 就看你認為維護會不會很麻煩來決定是否採用.

台灣統xERP,大陸速xERP,都是用的sql server .都不用identity字段.他們還是用整數做Primary key,但不是identity.這種安排的一個重要原因是主從表的同步問題.因為identity的值做主鍵必須等存盤成功後才知道到底是多少.而從表保存時就需要知道主表的primary key.我在第六部分說的」斷開主從關係」可能也與此相關.在微軟的體系中,他使用identity字段做主鍵.但他用的是嵌套的存儲過程來完成的.如果純面向對像開發來說,這個思路是好的,但對於我們borland族以dataset為中心的開發者來說.就不好用了.微軟例子可以見Duwamish.網上書店..我個人覺得基本表的主鍵可以用identity,主從表的主表是不能用的,從表其實也是可以用identity做主鍵的.
===================引 用 pedro756901 文 章===================
小弟在實作三層,SA覺得開自動編號對SQL Server效能及空間比較節省
但我Client在新增一筆資料時,自動編號欄位無法帶到前端來,
於是搜尋一下網路資料,發現大陸網友發表一篇
http://www.wangwa.com/info/2006-07/7.htm

講三層架構裡,Sql自動編號欄位不適合用

請問有無前輩開發三層的,主鍵是否有用到Integer自動編號成功過?
特別是那種MasterDetail單據....
謝謝指導

------
將問題盡快結案也是一種禮貌!
dyming
初階會員


發表:0
回覆:11
積分:32
註冊:2003-04-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-08-02 12:56:58 IP:61.218.xxx.xxx 未訂閱
用程式技巧吧.

identity 確實要存檔後才會產生, 所以主檔新增時先將此欄位預給0, 明細新增時當然也給0, 就解決了主從連結問題.
存檔時當然此欄位不可寫回 (用 TUpdateSQL 避掉此欄位), 主檔先 ApplyUpdates, 於是 identity 欄位就可從主檔 select 出來,
再將此值異動明細欄位, 明細存檔就解決了.
pedro
尊榮會員


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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-08-02 15:23:35 IP:60.248.xxx.xxx 未訂閱
謝謝danny版主還有dyming回應

如原作者所述問題點

dyming兄您講的這種,存完檔需要再下一次Query,前端才知道剛剛所存的單據號碼,
不知道實作起來容不容易,還有效能如何?

我有想過把identity取消,直接用select max(bilno) from xxxx,取得最大單號,再加一方式
不過用於多Client端會搶號及Server--->Client一來一往耗時

只是好奇為什麼Integer欄位,普遍都不使用? 一定有其它刺手因素在吧?

===================引 用 dyming 文 章===================
identity 確實要存檔後才會產生, 所以主檔新增時先將此欄位預給0, 明細新增時當然也給0, 就解決了主從連結問題.
存檔時當然此欄位不可寫回 (用 TUpdateSQL 避掉此欄位), 主檔先 ApplyUpdates, 於是 identity 欄位就可從主檔 select 出來,
再將此值異動明細欄位, 明細存檔就解決了.
danny
版主


發表:100
回覆:522
積分:595
註冊:2002-03-11

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-08-02 15:55:45 IP:203.79.xxx.xxx 訂閱
也沒有到 "Integer欄位,普遍都不使用" 吧 ? 這要看你設計的作法而定, 其實我就是使用 Integer.
取單號可以透過特定的 function 確保取得的單號是維一的, Detail 在 Insert 時直接抓 Master 的 Integer
你也可以使用 dyming兄的方式, 先填某一個值(如: 0)給Detail, 等到 AP Server 真的取得 identity 再寫入取得的值.
identity 的優點是單號一定會是正確的(唯一的, 給Database處理掉), 而用 Integer 還要自己處理, 當然可以自己加上自訂的單號邏輯(彈性).

===================引 用 pedro756901 文 章===================
謝謝danny版主還有dyming回應

如原作者所述問題點

dyming兄您講的這種,存完檔需要再下一次Query,前端才知道剛剛所存的單據號碼,
不知道實作起來容不容易,還有效能如何?

我有想過把identity取消,直接用select max(bilno) from xxxx,取得最大單號,再加一方式
不過用於多Client端會搶號及Server--->Client一來一往耗時

只是好奇為什麼Integer欄位,普遍都不使用? 一定有其它刺手因素在吧?

===================引 用 dyming 文 章===================
identity 確實要存檔後才會產生, 所以主檔新增時先將此欄位預給0, 明細新增時當然也給0, 就解決了主從連結問題.
存檔時當然此欄位不可寫回 (用 TUpdateSQL 避掉此欄位), 主檔先 ApplyUpdates, 於是 identity 欄位就可從主檔 select 出來,
再將此值異動明細欄位, 明細存檔就解決了.
------
將問題盡快結案也是一種禮貌!
pedro
尊榮會員


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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-08-03 10:17:22 IP:60.248.xxx.xxx 未訂閱
請問danny版主

如何維護每個Client端只取一個不重覆的單號?
單號如何方便查詢? 如果我用varchar單號欄位
例如960803xxxxxx3,我可輸入960803查96年8月3號所有單據(Like '960803%')
用整數就得加開一個Varchar日期欄位

維護時sql語法用Integer方便麼? 例如我要統計960801到960831未出貨的情況?

===================引 用 danny 文 章===================
也沒有到 "Integer欄位,普遍都不使用" 吧 ? 這要看你設計的作法而定, 其實我就是使用 Integer.
取單號可以透過特定的 function 確保取得的單號是維一的, Detail 在 Insert? 時直接抓 Master 的 Integer
你也可以使用 dyming兄的方式, 先填某一個值(如: 0)給Detail, 等到 AP Server 真的取得 identity 再寫入取得的值.
identity 的優點是單號一定會是正確的(唯一的, 給Database處理掉), 而用 Integer 還要自己處理, 當然可以自己加上自訂的單號邏輯(彈性).
VICSYS
初階會員


發表:21
回覆:64
積分:32
註冊:2002-10-10

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-08-12 01:34:12 IP:219.68.xxx.xxx 未訂閱
對不起! 插花一下

單據自動編號, 不是本來就應該這樣做嗎?

1.用 ClientDataSet 元件, 採用 DataSetField 的方式連接
2.DataSetProvider 加入 poPropogateChanges
3.在 DataSetProvider 的 BeforeUpdateRecord 取得自動編號
ex.
if (SourceDS = MasterDataSet) and ( UpdateKind=ukInsert ) then
begin
SELECT MAX(NO) MAXNO FROM SOMETABE WHERE DATE LIKE '960803%'
DeltaDS.FieldByName('BILLNO').NewValue:= MAXNO 1
end;

這時如果使用者只輸入1筆主檔, 並輸入了明細資料, 然後存檔, 這時編號會回傳至 Client 端!
明細的單號也會正確地異動! 如果您是在 Client 用 MasterSource 方式來連接 M/D 就做不到!
只能用 DataSetField 的方式

1.您還必須解決如果使用者 同時輸入多筆主檔, 之後才一起存檔的情況, 這時會在在Client端造成
主鍵重覆(或者是空白)的問題, 但這個問題很好解決, 只要給一個假的唯一的序號即可,
反正 ApplyUpdate 後, 單號會重新取得!

2.DataSetField 的連接方式, 會把該主檔的明細全部讀入!
如果明細資料一多的話, 這會造成問題, 這時個只好改寫 ClientDataSet 的元件!

標題是:使用主鍵(integer)自動產生,是好是壞?
所以我想真正的問題應該是 Insert 之後, 回傳的問題! 而且是當主鍵
不是用 Delphi 去計算得知主鍵! Max(NO) 1, 會知道 Max(NO) 1 的結果

自動欄位, 去取得資料庫的最大編號 1, 就是存入資料庫的真實值嗎?
如果是, 那麼沒有問題! 如果不是呢? 像 Oracle 的 ROWID, 只有存入資料庫後
才會得知, 那麼只好改寫 DataSetProvider 的元件,
只好把 Insert 部份的用自行開發程式來解決回傳的問題!

結論是, 我不用"使用主鍵(integer)自動產生", ROWID 的問題就很大了, 還來一個自動產生的主鍵?
pedro
尊榮會員


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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-08-13 11:02:30 IP:60.248.xxx.xxx 未訂閱
謝謝VICSYS兄回應

誠如您所言,主鍵用Integer連動的地方蠻多的,程式針對這些情況處理,越雜出問題的機會越有可能(維護成本越高),danny版主也提供可行的辦法

目前我的系統還是用VarChar,只是一直在被這個問題困擾

也只能採折衷的辦法,單號都用varchar,方便查詢及使用like
單檔流水號可用Integer,以max(no)取得

danny
版主


發表:100
回覆:522
積分:595
註冊:2002-03-11

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-08-13 11:41:29 IP:203.79.xxx.xxx 訂閱
這要用 database 的 Transaction 來作, 發生 error 就是有人在更新(retry), 沒有 error 就流水號加一, 再更新回 Table
以上作法亦適用於varchar單號欄位, 當然單號的 format 你要自定(你說的 xxxxxx3就是流水號)
還有一種作法也可以使用, 在 APP Server 那層用一個 Integer 變數紀錄流水號, Client 來要單號就將此 Integer 變數流水號加一(排除你的設計不會同時取單號的可能)

===================引 用 pedro756901 文 章===================
請問danny版主

如何維護每個Client端只取一個不重覆的單號?
單號如何方便查詢? 如果我用varchar單號欄位
例如960803xxxxxx3,我可輸入960803查96年8月3號所有單據(Like '960803%')
用整數就得加開一個Varchar日期欄位

維護時sql語法用Integer方便麼? 例如我要統計960801到960831未出貨的情況?
------
將問題盡快結案也是一種禮貌!
系統時間:2024-05-17 12:42:31
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!