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

資料庫Select太快...Insert太慢...該怎麼解決??

尚未結案
Angi
一般會員


發表:16
回覆:56
積分:14
註冊:2005-01-12

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-03-30 11:42:51 IP:211.20.xxx.xxx 未訂閱
請問一下喔! 我在做Insert前,會先select流水號,做成一個唯一的編碼 再寫入資料庫 可是,當迴圈在run時,卻會有二筆資料同時取到同一個流水號,因為insert還沒完成,select就又再度執行了,這該怎麼做呢? 舉例: for i := 1 to (product_x_nums 1) do begin //取得今天的日期時間 tmp_nowdate := FormatDateTime('yyyy-mm-dd hh:mm:ss', Now); //取得資料庫同一時間的下一個編號(編號格式:年月日時分秒加二位流水號) tmp_expend_detail_code := IncludeFunction.NextCodeExpend(tmp_nowdate, 'member_expend_detail'); //取得流水號 code := Copy(tmp_expend_detail_code,15,2); tmp_str := 'INSERT INTO member_expend_detail (expend_detail_code,date,code) VALUES (''' tmp_expend_detail_code ''',''' tmp_nowdate ''',''' code ''')'; //寫入資料庫的function Includefunction.sql_add_expend(tmp_str); //showmessage(tmp_str); end; 這個程式撰寫上是否有什麼問題,因為常會出現key重覆,只要把showmessage加上,就不會重覆了,請問各位大大是否有好的解決方法呢?
pillar62
資深會員


發表:9
回覆:324
積分:271
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-03-30 12:29:29 IP:210.64.xxx.xxx 未訂閱
你好 如果已經取到第一筆資料又可以確定同時間不會有人一起處理的話,建議可以直接用累加流水號的方式處理!! Pillar Wang
------
Pillar Wang
scotthsiao
高階會員


發表:13
回覆:324
積分:147
註冊:2005-02-01

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-03-30 13:14:09 IP:211.21.xxx.xxx 未訂閱
1. 使用 store procedure 自動給號 2. 使用 自動累加的欄位,每加一筆資料就會加一
Angi
一般會員


發表:16
回覆:56
積分:14
註冊:2005-01-12

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-03-30 13:38:55 IP:211.20.xxx.xxx 未訂閱
請問scotthsiao 大大 何謂 "使用 store procedure 自動給號"?? 資料庫中的PK是expend_detail_code code就是要用來累加的 現在的問題就是 在第一個select完成,取得code=1,但insert未完成 第二個select就先做了,由於insert未完成,所以code也是等於1 在不改資料庫的情況下,有辦法完成我要的動作嗎??
scotthsiao
高階會員


發表:13
回覆:324
積分:147
註冊:2005-02-01

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-03-30 14:06:04 IP:211.21.xxx.xxx 未訂閱
Stroe procedure 的方式 : 預先寫好料號的給號程序,在 Insert 的當下才啟動並自動存入新料號。 或者 : 新開立一個料號 Table,每次 SELECT 後立即在此 Table 新增新號碼,Insert 時就不會重複了。
timhuang
尊榮會員


發表:78
回覆:1815
積分:1608
註冊:2002-07-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-03-30 18:26:33 IP:203.95.xxx.xxx 未訂閱
Hi, 有種做法給你參考, 在 insert 的時候直接 select max 的語法來進行即可, 看你的資料庫種類, 稍微修改一下即可使用, 如, insert into member_expend_detail ('expend_detail_code', 'f1', 'f2') select isnull(max(expend_detail_code), 0) 1, 'my f1 value', 'my f2 value' from member_expend_detail 利用這種語法, 可以在 insert 的同時, 取得最大值加一, 就可以避免掉這個問題.
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-03-30 21:36:09 IP:218.32.xxx.xxx 未訂閱
有一些疑問個人感到不解: 1. 若是多使用者同時新增, 這問題依然無解. 2. 若是該程式是單一 Thread, 且未包 Transaction, 何以會有這問題...
scotthsiao
高階會員


發表:13
回覆:324
積分:147
註冊:2005-02-01

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-03-31 08:42:07 IP:211.21.xxx.xxx 未訂閱
經驗分享一下 : 這種問題早在 DOS Clipper 時代就有了,當時為了避免重複只得預先給號,如果使用者輸入一半就放棄了,號碼也還會留著,只是要註明無效。 後來證明有用,同時也符合會計的要求,就一直沿用到 SQL 資料庫。
change.jian
版主


發表:29
回覆:620
積分:439
註冊:2003-06-02

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-03-31 14:15:22 IP:59.120.xxx.xxx 未訂閱
我的解法: 1.把insert into的動作改到store procedure裡去執行.由store procedure裡去取最大的流水號.這樣,不管幾個人都不要理他,因為資料庫會去處理. 2.利用trigger去處理.在insert時才去取最大流水號加1
Angi
一般會員


發表:16
回覆:56
積分:14
註冊:2005-01-12

發送簡訊給我
#10 引用回覆 回覆 發表時間:2005-03-31 15:39:09 IP:211.20.xxx.xxx 未訂閱
可不可以舉實例呢?? 我還是不太了也...
lcjan
初階會員


發表:11
回覆:60
積分:29
註冊:2002-03-13

發送簡訊給我
#11 引用回覆 回覆 發表時間:2005-03-31 23:14:38 IP:218.170.xxx.xxx 未訂閱
引言: 請問scotthsiao 大大 何謂 "使用 store procedure 自動給號"?? 資料庫中的PK是expend_detail_code code就是要用來累加的 現在的問題就是 在第一個select完成,取得code=1,但insert未完成 第二個select就先做了,由於insert未完成,所以code也是等於1 在不改資料庫的情況下,有辦法完成我要的動作嗎??
1. 請問您是使用何種資料庫? 2. 取號部分可否使用 Sequence. 3. 整個迴圈是在同一個Transaction嗎? IncludeFunction.NextCodeExpend若是StoreProcedure或Database Fubnction,或由另一Session來讀取,且你在INSERT 第一筆資料後資料庫並未真正commit,那在第二筆取值時若非同一Transaction,極有可能會取到原來的值. 以上是我的推測..
Angi
一般會員


發表:16
回覆:56
積分:14
註冊:2005-01-12

發送簡訊給我
#12 引用回覆 回覆 發表時間:2005-04-01 17:20:37 IP:211.20.xxx.xxx 未訂閱
1. 請問您是使用何種資料庫? Mysql 2. 取號部分可否使用 Sequence. 什麼是Sequence?? 3. 整個迴圈是在同一個Transaction嗎? 同一個transaction IncludeFunction.NextCodeExpend 是function "並未真正commit"..我猜也是...不過不知怎麼讓它commit
pillar62
資深會員


發表:9
回覆:324
積分:271
註冊:2002-04-15

發送簡訊給我
#13 引用回覆 回覆 發表時間:2005-04-01 17:33:17 IP:210.64.xxx.xxx 未訂閱
你好 1.請問你是用mySql那一個版本,是否有支援transation?? 2.如果你有執行starttransaction那你跟資料庫查詢出來的資料一定都會一樣,因為在還沒有commit之前,資料不會確實存到資料庫!! 3.建議還是用給流水號的方式進行給號的動作!! Pillar Wang
------
Pillar Wang
lcjan
初階會員


發表:11
回覆:60
積分:29
註冊:2002-03-13

發送簡訊給我
#14 引用回覆 回覆 發表時間:2005-04-01 17:49:32 IP:211.23.xxx.xxx 未訂閱
引言: 1. 請問您是使用何種資料庫? Mysql 2. 取號部分可否使用 Sequence. 什麼是Sequence?? 3. 整個迴圈是在同一個Transaction嗎? 同一個transaction IncludeFunction.NextCodeExpend 是function "並未真正commit"..我猜也是...不過不知怎麼讓它commit
抱歉!我是使用Oracle,MySql並不熟. sequence是oracle中的自動給號物件. Database1.StartTransaction; //啟動交易 Database1.Rollback; //取消交易 Database1.Commit; //確認交易 ADOConnection1.BeginTrans; //啟動交易 ADOConnection1.RollbackTrans; //取消交易 ADOConnection1.CommitTrans; //確認交易 另外,你的迴圈Insert號碼如果是連續的,可否改變一下. 先在迴圈前取得第一號,以變數儲存,迴圈中來作Insert,並累加該變數. 這樣也可避免未commit而產生PK重複問題.
DragonLucky
一般會員


發表:0
回覆:1
積分:0
註冊:2003-10-15

發送簡訊給我
#15 引用回覆 回覆 發表時間:2005-04-02 09:32:36 IP:219.134.xxx.xxx 未訂閱
我的做法是, 寫一各取得號碼的Procedure , 然後在這存檔前判斷表格是否為Insert, 如果為Insert, 那麼就調用取的號碼的這个Procedure, 這樣就不會重複, 我寫的程式都是使用這種方式
Angi
一般會員


發表:16
回覆:56
積分:14
註冊:2005-01-12

發送簡訊給我
#16 引用回覆 回覆 發表時間:2005-04-02 09:49:20 IP:211.20.xxx.xxx 未訂閱
引言1: 1.請問你是用mySql那一個版本,是否有支援transation?? 2.如果你有執行starttransaction那你跟資料庫查詢出來的資料一定都會一樣,因為在還沒有commit之前,資料不會確實存到資料庫!! 3.建議還是用給流水號的方式進行給號的動作!! 1.確定是有支援transaction 2.我就是不知如何確認commit,我在insert後加入一段空迴圈,跑1~180,就可以確認資料已寫入 3.因為其它需求,沒有辦法使用自動給號的pk 引言2: 另外,你的迴圈Insert號碼如果是連續的,可否改變一下. 先在迴圈前取得第一號,以變數儲存,迴圈中來作Insert,並累加該變數. 這樣也可避免未commit而產生PK重複問題. 我也有想過,但是,想請教一下,若不同台機器執行這個檔,而流水號必須全部一起累加,那會不會產生另一個問題? 引言3: 我的做法是, 寫一各取得號碼的Procedure , 然後在這存檔前判斷表格是否為Insert, 如果為Insert, 那麼就調用取的號碼的這个Procedure, 這樣就不會重複, 我寫的程式都是使用這種方式 其實我現在也是類似這個概念,但是就不知道如何"存檔前判斷表格是否為Insert"
lcjan
初階會員


發表:11
回覆:60
積分:29
註冊:2002-03-13

發送簡訊給我
#17 引用回覆 回覆 發表時間:2005-04-02 15:25:02 IP:218.174.xxx.xxx 未訂閱
引言: 引言2: 另外,你的迴圈Insert號碼如果是連續的,可否改變一下. 先在迴圈前取得第一號,以變數儲存,迴圈中來作Insert,並累加該變數. 這樣也可避免未commit而產生PK重複問題. 我也有想過,但是,想請教一下,若不同台機器執行這個檔,而流水號必須全部一起累加,那會不會產生另一個問題?
1. 你取號與Insert的Procedure可以用同一個Query作嗎?以確保他們都在同一transation中. 2. 另外提供一個做法, 以Table儲存序號,取號後馬上Update 加 1.
Angi
一般會員


發表:16
回覆:56
積分:14
註冊:2005-01-12

發送簡訊給我
#18 引用回覆 回覆 發表時間:2005-04-04 17:01:11 IP:211.20.xxx.xxx 未訂閱
Q: 1. 你取號與Insert的Procedure可以用同一個Query作嗎?以確保他們都在同一transation中. 2. 另外提供一個做法, 以Table儲存序號,取號後馬上Update 加 1. A: 1.是同一個Query也是不行,一樣的結果 2.以table儲存序號,馬上update,那和馬上insert不是一樣嗎??難道不會在未update前,就先再度select嗎??
lcjan
初階會員


發表:11
回覆:60
積分:29
註冊:2002-03-13

發送簡訊給我
#19 引用回覆 回覆 發表時間:2005-04-04 17:36:03 IP:61.59.xxx.xxx 未訂閱
引言: Q: 1. 你取號與Insert的Procedure可以用同一個Query作嗎?以確保他們都在同一transation中. 2. 另外提供一個做法, 以Table儲存序號,取號後馬上Update 加 1. A: 1.是同一個Query也是不行,一樣的結果 2.以table儲存序號,馬上update,那和馬上insert不是一樣嗎??難道不會在未update前,就先再度select嗎??
這問題可能必須回到"如何確認MySQL已經commit" 在Oracle上我還沒遇到此類問題,且我對MySQL不熟 提供一些參考方向: TDatabase的Translsolation設定值 TDatabase的HandleShared設定值 TQuery的RequestLive設定值 BDE 的 SQLPASSTHUR MODE參數 希望對您有幫助
a6475
高階會員


發表:67
回覆:230
積分:154
註冊:2002-09-15

發送簡訊給我
#20 引用回覆 回覆 發表時間:2005-04-06 10:29:35 IP:211.23.xxx.xxx 未訂閱
我之前也有遇過累似的問題 取得唯一的編號我是用 流水號+時間 由於Delphi的時間是浮點數,只要取小數點之後的數字 大約比豪秒還少。    這樣號碼重覆的幾率會非常的小    ..-----------βλμε------------..
◎Oo月夜 光明 藍更愁oO◎
藍調月光城v4:http://inping.myweb.hinet.net/ (暫時使用中..) 明日報(藍調.月光):http://mypaper2.ttimes.com.tw/user/a6475
------
月夜 光明 藍更愁
Angi
一般會員


發表:16
回覆:56
積分:14
註冊:2005-01-12

發送簡訊給我
#21 引用回覆 回覆 發表時間:2005-04-07 13:42:10 IP:211.20.xxx.xxx 未訂閱
最後我使用了這個方法 引言 lcjan: 另外,你的迴圈Insert號碼如果是連續的,可否改變一下. 先在迴圈前取得第一號,以變數儲存,迴圈中來作Insert,並累加該變數. 這樣也可避免未commit而產生PK重複問題. 除此之外,就是要注意資料庫的PK 因為原來我以datetime加流水號這個欄位為PK 資料的重覆機率太高 後來,多加了一個卡號的欄位,使得重覆的可能性降低 而且每次一個卡號不可能同時在不同地方使用 自然就可以使用Icjan的方法 所以,其實是我自己在設PK時,沒有考慮清楚 不過,非常謝謝各位大大的寶貴意見,thanks!
系統時間:2024-07-02 0:18:08
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!