作者 主題: 如何有效率產生亂數唯一值寫入資料庫當主鍵?  (閱讀 18337 次)

0 會員 與 1 訪客 正在閱讀本文。

huangxianqin

  • 憂鬱的高中生
  • ***
  • 文章數: 129
    • 檢視個人資料
小弟的想法是希望寫個函式,能夠隨機產生一組數字作為訂單編號,該數值不能夠重複!

大致查書的說明,以這種需求大概作法是每次產生出來的數字都作一次資料庫比對動作...沒有找到相符的即寫入資料庫內......我想隨著時間久後這樣的方式會嚴重降低程式效能吧?

詢問朋友提供一種思考的方式,根據所需的長度設一個陣列,例如我要產生五位數的亂數則設一array[100000]...然後每次產生的亂數都去檢查陣列對應的值為0或1,0就改為1並寫入資料庫中.....

這樣等於是把sql查詢動作轉為php程式執行,但是不知道如何把該陣列設為永久保存?php有辦法作嗎?:o
不知道其他大大是否能提供小弟更好的作法@@" 懇請指教~~ :)

最直接的大概是用mysql的auto_increasement吧....但是覺得這樣有點太過基礎@@...

梁楓

  • 俺是博士!
  • *****
  • 文章數: 6220
    • 檢視個人資料
有一個重點是
為什麼“序號”比“亂數”差?
先想好你的用途,在來重新想這個功能

huangxianqin

  • 憂鬱的高中生
  • ***
  • 文章數: 129
    • 檢視個人資料
老實說.......純粹是個人想像,加上想以auto_increasement以外的方式來實做這樣的需求 :oops:

至於未啥未認為序號比亂數差的想法是我覺得設000001的編號跟524331之類的編號看似更有效果(感覺交易了很多似的@@),當然這純粹是小弟單方面的想法啦

我剛剛有在與人討論研究,有人提供意見是:利用流水序號為參數作加密編碼後來當最後要的序號......聽起來是多費了一層包裝的感覺~~

Yamaka

  • 俺是博士!
  • *****
  • 文章數: 4913
    • 檢視個人資料
    • http://www.ecmagic.com
引述: "huangxianqin"
至於未啥未認為序號比亂數差的想法是我覺得設000001的編號跟524331之類的編號看似更有效果(感覺交易了很多似的@@),當然這純粹是小弟單方面的想法啦


將序號設為 524000 開始不就好了  :o

梁楓

  • 俺是博士!
  • *****
  • 文章數: 6220
    • 檢視個人資料
然後在轉十六進位

chaofu

  • 可愛的小學生
  • *
  • 文章數: 15
    • 檢視個人資料
訂單單號若是用"亂數惟一值"為主KEY,
那我想... 很多部門的人(會用到訂單系統的人)會想殺人吧...

slime

  • 俺是博士!
  • *****
  • 文章數: 1692
    • 檢視個人資料
引述: "huangxianqin"
大致查書的說明,以這種需求大概作法是每次產生出來的數字都作一次資料庫比對動作...沒有找到相符的即寫入資料庫內......我想隨著時間久後這樣的方式會嚴重降低程式效能吧?

詢問朋友提供一種思考的方式,根據所需的長度設一個陣列,例如我要產生五位數的亂數則設一array[100000]...然後每次產生的亂數都去檢查陣列對應的值為0或1,0就改為1並寫入資料庫中.....


這樣動作的目的跟資料庫的索引有什麼不同嗎?
冷笑話: 我的 IP 是 127.0.0.1

梁楓

  • 俺是博士!
  • *****
  • 文章數: 6220
    • 檢視個人資料
我常幹這種事
資料庫為序號
把數字加上一定的量(比如12345)
然後在用16進位輸出到client端
看起來多完美啊 XD

anderson1127

  • 訪客
這種方式叫做惡搞 , 企圖用這種手法綁死該企業對該Programmer的依賴性
順道也讓接手者完全摸不著頭緒為何要這樣做!!

要產生訂單編號,常見的做法都是以西元年月日時,再加上幾個位數的數字
來代表訂單編號,光是這樣做就完全不會重複,也不會造成system loading
簡單的idea不用,要去用你這個爛方法 !?

梁楓

  • 俺是博士!
  • *****
  • 文章數: 6220
    • 檢視個人資料
1. 每組數字要有意義,這種編碼原則當然要交接,有人告訴你這些是不需要交接的?有那個企業不會要求對該編碼的方式完全了解嗎?
2. 有人告訴你我的編碼裡沒有日期嗎?
3. 你不知道許多人不願意讓表單上的資料可以直接看懂許多訊息嗎?

我不知道你為企業進行過多少專案
但你的口氣可以好一點
並不會你說idea 爛我就會認同你

你可以提出更好的方式來討論

ricky

  • 區域板主
  • 鑽研的研究生
  • *****
  • 文章數: 669
    • 檢視個人資料
    • Ricky 碎碎唸
在實際應用時不用連續值也是有顧慮的
通常使用連續值作為訂單編號
其他的競爭對手很容易從訂單的編號推算出你每天大約有幾筆的訂單
時間資訊通常都會額外紀錄在DB中,不會顯現在訂單編號上
樓主如果是因為這個顧慮的話
您可以參考一下GUID或是UUID這類的演算法
或是上google查詢一下
有很多現成的模組可以使用
我的symfony作品:YOMOpets 寵物誌
有興趣可以一起來討論symfony喔
我的部落格:http://ricky.ez2.us/

SunsetKiller

  • 可愛的小學生
  • *
  • 文章數: 10
    • 檢視個人資料
    • 阿宅
訂單編號當主鍵不恰當吧.
用 auto_increasement 當主鍵, 把訂單編號存到其它欄位, 再index訂單編號的欄位, 在執行的效率會比較好.

另外訂單編號性質和產品編號類似
就和一般公司在編產品編號時, 會給一組格式化的產品代碼. 有可能是這樣.

代碼: [選擇]
CDR070011

外人不知道, 但公司內部可能是這樣定義

代碼: [選擇]
CDR-07-001-1

CDR => 光碟片 (A)
07 => 2007年 (B)
001 => 2007年的第一款 (C)
1 => 亂數確認碼 (D)

所以訂單編號不可能會重覆阿.
在存入資料庫時, 只先
代碼: [選擇]
select * from table where 年份 = "2007" 產品分區="CDR"
得知有多少筆結果後, 再存入新資料時. 在把這個數值+1存入(C), (D)的部份取1-9的亂數, 這樣就解決了吧  :wink:

梁楓

  • 俺是博士!
  • *****
  • 文章數: 6220
    • 檢視個人資料
在“外的編碼”,不見得是“資料庫裡的資料”

到外面的“編碼”都可能是被“加工後的資料”
系統可能還是用 auto_increment 來處理
然後在視公司的狀況加入資料來處理

我目前處理過最長的bar code 是32 碼

處理過最誇張的是業主要連庫存位置都記在bar code 上...

wuposheng

  • 憂鬱的高中生
  • ***
  • 文章數: 172
    • 檢視個人資料
其實訂單編號應該是公司訂的,不應該是工程師自已訂的吧~~
除非用這程式的是新成立的公司,那可能就要follow你的架構
如果同行發現你今日出貨量是多少的話,你就不要在你的編號上加上日期
但還是可以用順序的方式來完成~~在管理上也方便
不過我想要用亂序或是順序,各家公司會有自已的規格吧

梁楓

  • 俺是博士!
  • *****
  • 文章數: 6220
    • 檢視個人資料
工程師的價值,在於提供可靠又可信的方案讓客戶選擇
好的工程師不但要提供客戶可靠又右信的方案外
還要從客戶提出來的規格裡找到往後可能會出現的問題進行分析

wuposheng

  • 憂鬱的高中生
  • ***
  • 文章數: 172
    • 檢視個人資料
是沒錯,但是針對的角度不同
今天如果針對的是外面的客戶,當然會給很多方案
但如果今天針對的是自已的公司,不見得提供的意見可以被接受
或許應該這樣說~~今天針對的是序號這個case
我想用亂序來做為申單編號的可行度應該不高~~這就不見得是好的見議呀
假如是待開發的case,工程師本來就是有很多地方要提出來討論改進的
有討論才有進步呀~~我也是在失敗中求進步~~cc

jou

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 4989
  • 性別: 男
    • 檢視個人資料
其實那些"產品識別碼"加碼加密有可能都是在做心酸的啦!
業務為了跟客戶"搏麻吉",早就把那一串"產品識別碼"的定義告訴客戶了。
但是原 po 要訂單號碼當訂單檔的主 KEY 的話,不就是日期+流水序號,這麼簡單!

然後,流水序號是有一個檔案專門在做記錄,記錄目前用到第幾號。
再考慮到多人多工同時打單,所以流水序號是在單據確定寫入時,才編入單據號碼的。
同時加 1 寫入流水序號記錄檔!

梁楓

  • 俺是博士!
  • *****
  • 文章數: 6220
    • 檢視個人資料
我也處理過一個客戶
工廠、產線、班次、產品型號、生產日期、生產序號全在上面

如果“單純對訂單”可能不會做到那麼復雜
但做到“機器序號”就可能有需要了

shengeih

  • 鑽研的研究生
  • *****
  • 文章數: 970
    • 檢視個人資料
PK 歸 PK ,編號歸編號...兩者分割開來做,是不是會比好些?

梁楓

  • 俺是博士!
  • *****
  • 文章數: 6220
    • 檢視個人資料
shengeih 對啊 沒錯啊
我一開始就講了啊
我的資料庫“一樣是序號”
只是“加上一些方式比較不容易由字面上直接解讀”
然後教客戶怎麼用計算機解碼就好
呵呵

dean

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 1279
  • 性別: 男
  • 有些人,有些事,值得.
    • 檢視個人資料
先不管你的用途啦,就純粹討論概念.

用一種簡單的亂數抽號碼牌機制,這是我跟team members討論程式設計時的用語,可以視為一種design pattern

先準備好一個collection, 裏面放你的序號集合(例如000001~999999).然後再用亂數去取出來放進DB內.而取過的值要從collection中移除,同時collection.items.count 的值要減一.

每次取亂數的範圍用1~n,n為collection.items.count

像不像是你把一堆寫好的號碼牌丟進一個box,搖一搖後,再一個一個取出來??

概念懂了,應該就不難寫出來囉..

ricky

  • 區域板主
  • 鑽研的研究生
  • *****
  • 文章數: 669
    • 檢視個人資料
    • Ricky 碎碎唸
引述: "dean"
先不管你的用途啦,就純粹討論概念.

用一種簡單的亂數抽號碼牌機制,這是我跟team members討論程式設計時的用語,可以視為一種design pattern

先準備好一個collection, 裏面放你的序號集合(例如000001~999999).然後再用亂數去取出來放進DB內.而取過的值要從collection中移除,同時collection.items.count 的值要減一.

每次取亂數的範圍用1~n,n為collection.items.count

像不像是你把一堆寫好的號碼牌丟進一個box,搖一搖後,再一個一個取出來??

概念懂了,應該就不難寫出來囉..

這樣並不是一個很好的方式
畢竟你得事先準備一個空間來儲存
而且數量還得事先規劃好
不然破表了怎麼辦
就如同我先前說的
既然都是要弄個不重複的隨機號碼
何不採用GUID或是UUID演算法
幾乎是不可能重複的值
而且又不會佔用DB的資源不是嗎

-------------------------
GUID (Globally Unique Identifier)全區域唯一識別碼
意思是指在一台機器上產生的識別數字,
而且保證在同一個時空底下對所有機器都是唯一的。
簡單的說就是,全世界不會有人產生重複的GUID值。
他的演算法參考到許多識別的機制,像是網路卡號,時間,亂數....
我的symfony作品:YOMOpets 寵物誌
有興趣可以一起來討論symfony喔
我的部落格:http://ricky.ez2.us/

dean

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 1279
  • 性別: 男
  • 有些人,有些事,值得.
    • 檢視個人資料
嗯嗯,GUID是不錯呀..

只是..如果訂單號碼要有一定的格式時怎麼辦咧??


至於破表..就看編碼方式與長度啦,可以讓collection物件本身的方法去負責破表處理,或是把時間(年或月或日)拿進來當prefix,或是做兩個box,一開始抽box1當prefix,然後box2當body,當box2抽完時會去抽box1當prefix,並同時對box2進行initial;GUID不容易破表是因為byte數夠長.如果n(box1) * n(box2) 夠大到1000年都用不完..那應該不用擔心破表的問題了..

GUID我們也很常用,但這個case個人認為不太適合耶,GUID儘量不要用在"有可能"被拿來在人與人溝通間的訊息欄位上.另一方面也儘量不用在進DB debug時常需要拿來當線索的欄位上.