Re: [請益] 請問自動跳號該怎寫呢?
[寫在前頭] 寫完後才發覺說有點離題了,不過還是把自己的經驗放上來,希望大家不
要犯了些簡單的錯誤。
我們把問題定好:希望在資料未進資料庫前,就希望給將要進資料庫的某筆資料一個唯
一值。我整理一下可能的做法有:
1. 使用資料庫支援的方式
若使用使用的是 Oracle 或 PostgreSQL 這類有支援 sequence 物件的資料庫
的話,事情就相對的簡單,只要每次要編號時向 sequence 要個編號,當你領
了這個號碼後,它不會再發給別人相同的號碼,這樣可以保證你拿到的值的唯
一性
優點:
* 有資料庫保證,取到的值是唯一並且是連續的數字。
* 這是一個比較好的作法
缺點:
* 有資料庫限定:要用的是有支援 sequence 的資料庫
* 需要多學點東西:就算用了這樣的資料庫,也要知道要怎麼取
Sequence ,而不是只是呆呆的把 Oracle 當 MySQL 在用。
2. 自行實作 sequence
2.1 建表
因為不是每個資料庫都有 sequence 這樣的機制,但是大部份的資料庫也都像
MySQL, MSSQL 一樣有 Auto Increment 的功能。所以是可以建一張表來當做
sequence,當要編號時就新增一筆資料然後取它自動編號的值來用。
2.2 用鎖
找一個欄位,取值時將它上鎖,取完後加一,這樣來模擬 Sequence。
這通常會配合 Trigger
優點:
* 可以使用的資料庫變多,只要資料庫有支援自動編號或是鎖
缺點:
* 麻煩,很麻煩...
* 就算實作出來,也要記得怎麼用。當交接時沒有交接好,又沒有文
件時,事情就很精采了。
倘若只需要編號的唯一性,但是不需要保持編號的連續的話或是不需要保持編號的大
小關係的話(如後取的編號要比前取的大),可以用第三種方法
3. 使用 uniqid()
PHP 有提供一個產生唯一編號的函式 uniqid() ,它會產生以時間(精確到毫秒
)為依據的唯一號。到這一步,取到的值還可以有後取者較大的特性(但無法看
出誰是誰的上一個或下一個)。但通常我們會在取到這值後,再取MD5之類的
Hash ,就可以得到一個格式固定的 ID 值。
優點:
* 有 PHP 就可以拿來用,不需要資料庫支援
缺點:
* 取到的值不漂亮,不會是 0001, 0002 這樣的值,只有在只需要唯一
性的場合可以用。
* 雖然在數學上再怎麼證明以這種取法碰撞機率低到可以算是零,但是
還是會有人擔心會碰撞(大概他們寫的程式是出錯的話飛機會掉下來
或核電廠會爆炸)。若真的需要那麼嚴謹的話,應讓資料庫來負責這
種事。
我遇到的在這種問題上出錯的大部份是不太了解資料庫特性的新手,所以常會看到像
以下的句子:
$id = query("SELECT max(xxx_id) FROM TableA") + 1;
當寫完上面那句子後就很高興的拿這 $id 來用了。這樣的結果當然就是有一天客戶發
覺資料異常,怎會有該唯一的值卻不唯一。
這種程式碼不用說來寫核電廠的程式,光是個購物車的訂單就沒有辦法用,因為不可以
有兩張訂單的號碼是一樣的,而這種問題通常會在上線後才爆出來,因為在測試時不會
想到要測唯一性(只有保佑資料庫的欄位上有做唯一值的限制)。
(以上是真實事件....我們的人就爆過這種事被我找出來,希望不要再有這種事情發生
了)
--
政治是高明的騙術
化妝是高明的易容術
有了Photoshop就不用SK II
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 58.114.200.219
※ 編輯: pkwbim 來自: 58.114.200.219 (04/27 20:11)
討論串 (同標題文章)
完整討論串 (本文為第 2 之 2 篇):
5
17
PHP 近期熱門文章
PTT數位生活區 即時熱門文章