// 找到現在的「時間」
$ymdh = date('Y/m/d H');
// 用現在的時間找出訂單目前是有幾筆
$findOrderSoFar = mysqli_fetch_array($pdo->query(
"SELECT count(public_order_id) as num FROM `order_record`
WHERE FROM_UNIXTIME(add_time, '%Y/%m/%d %H') = '{$ymdh}' "
));
// 將 $i 直接加入目前幾筆的數量
$i = $findOrderSoFar['num'];
// 如果找到零比則從一開始
$findOrderSoFar['num'] == 0 ? $i = 1 : $i = $findOrderSoFar['num'];
// 開始迴圈
while ($row = mysqli_fetch_array($sql)) {
// 設定訂單長相
$_SESSION['public_order_id'] = substr(date('YmdH', time()), -8).str_pad($i, 4, '0' ,STR_PAD_LEFT);
// ...
$i ++;
}
我目前作法是這樣,但是卻還是會重複流水號
就是不同使用者同時下訂時仍然會有這情形發生
我的邏輯已經死了 LOL..
補充
訂單編號格式會是:
YYMMDDHH0001
產生序號的方式各位大大已經分享很多,想提供取得訂單編號之後的處理過程,當然不一定是最好的,可以參考一下。
do {
// 取得訂單編號
// 執行insert sql
// 取得sql error錯誤碼
$errorNo = getErrorNo(); // 請使用你目前程式取得錯誤碼的方式
// 資料重複以外的錯誤則停止迴圈
if ($errorNo > 0 && $errorNo != 1062) {
break;
}
} while ($errorNo == 1062); // 錯誤碼為1062則重複繼續迴圈
這個問題應該不是程式邏輯旳問題.
而是"取單號"後,到資料COMMIT 到TABLE 中的時間差問題.
可以從三個方向下手:
A.單據主檔的單號位設定為"唯一值"的主INDEX.當單號重覆時,資料庫會傳回錯誤碼給前端程式.前端程式要攔截錯誤碼後, 再重新取單號.直到 INSERT 成功為止.
B.改變單號編碼還輯: 將機台編號或部門編號或員工編號...等擇一或擇二加入單號的編碼原則中.以降低重覆機率.
C.縮短"取單號"到COMMIT之間的時間差.如資料輸入時先不取單號,等除了單號外其他資料輸入完畢後,準備要INSERT進TABLE時,才取單號,取完後,立即INSERT 進TABLE .INSERT OK 後,再重新DISPLAY畫面.(將單號資料顯示在畫面上)
發現你程式幾個問題要注意。
三元判斷式不是給你這樣用的啦。而且,你根本不需要再去判斷。直接+1就好了。
三元判斷式的正規用法是
$findOrderSoFar['num'] == 0 ? $i = 1 : $i = $findOrderSoFar['num'];
改成
$i = $findOrderSoFar['num'] == 0 ? 1 : $findOrderSoFar['num'];
這才是正確的三元應用寫法。
不過在這邊,不知道你有沒有注意到。無論是0筆還是1筆。其i值都是1。這不是很奇怪嗎?
所以你的
$i = $findOrderSoFar['num'];
直接改成
$i = $findOrderSoFar['num']+1;
就可以了。那個三元判斷式就拿掉不要用它了。
再來是建議的做法。其實一般自定義的流水號,也最好不要直接取資料值數量。
可以的話,可以建一個設定檔的新表。來將值暫存在此。
我的想法是這樣
order_record
id | add_time | status |
---|---|---|
AUTO_INCRESMENT id | 提交時間 | 狀態,刪除或是棄用設定為 0 |
insert
到表中。(如果是填資料之前,status
可以設定為 -1
或其他數字)。update
處理訂單。該筆 id - 該區間第一筆 id + 1
。Oracle有一個好用的語法:
Select .... for Update
之前看前輩就用這個指令解決了樓主取號重複的問題。
搜尋select for update DB類型,應該可以解決您的問題
1.做一個取訂單的副程式
2.在新增訂單時都去SQL取新的號碼
OrderNumber=OrderNumber_App()
3.用i+1有可能重覆