|
VFP 愛用者社區 本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
|
上一篇主題 :: 下一篇主題 |
發表人 |
內容 |
jasonyummy
註冊時間: 2004-05-06 文章: 15
第 1 樓
|
發表於: 星期四 六月 10, 2004 4:12 pm 文章主題: oldval() 與 curval() 的問題 |
|
|
如題:
我在開發遠端資料庫, 後端用的是 SQL2000 前端用的是 vfP 6.0 sp5
我在前端設立一條通道 connect1 ,非同步執行與批次處理都有打勾
*---
然後利用此通道建立了一個 view 名為 outp_v (後端sql為outp) [銷貨主擋]
與 opitem_v (後端sql為opitem) [銷貨明細擋]
*---
此 outp 設了索引 為 tradeno(單號)
此 opitem 設了兩個共同索引 為 tradeno(單號) line_no(項次)
*------
然後設計了一個 form
把 outp_v 與 opitem_v 都拉了進來
outp_v buffer 設 3
opitem_v buffer 設 5
*---
最近有一問題困擾了我很久, 查了vfp的說明,明明寫的很清楚.
可以用 oldval() , curval() 來判斷是否有人先一步更改資料,
但經過我的測試結果, 很奇怪
例如:
有一張銷貨單 單號 A001 貨號 CCC 單價 100 項次 1
欄位名 tradeno,goodno,saleprice,line_no
有二人 A , B
1.
A先打開 form 叫出單號 A001的銷貨單
把 opitem_v 內的 銷貨單價 saleprice 100 修正成 50
尚未存檔
oldval('saleprice')=100
curval('saleprice')=100
saleprice=50
2.
B此時進來,也打開 A001
尚未修改時,用 oldval(),curval()看時
oldval('saleprice')=100
curval('saleprice')=100
saleprice=100
現在B修正 saleprice為 10
此時再看一次
oldval('saleprice')=100
curval('saleprice')=100
saleprice=10
好,把它存檔 用 tableupdate(.t.,.f.)結果回覆成功=.T.
此時再看一次, 結果都變成了 10
oldval('saleprice')=10
curval('saleprice')=10
saleprice=10
3.
這時回到 A
先看一下, 還是沒有變
oldval('saleprice')=100
curval('saleprice')=100
saleprice=50
到這裡時我就感到很奇怪, 不是B已經修改成 10 ,為何還是不變呢?
不是可以用oldval(),curval()來判斷嗎?
4.
然後我不管的繼續
把A也一樣的存檔, 用 tableupdate(.T.,.F.) 結果回覆不成功=.F.
錯誤訊息=1585 (記錄已被其他使用者修改)
真奇怪, 它知道有被更改,但是為何oldval(),curval() 的值不變呢?
此時,我只好用 tableupdate(.T.,.T.)來強制存檔,結果回覆成功=.T.
這時我再看一次, 都變成 50
oldval('saleprice')=50
curval('saleprice')=50
saleprice=50
為了這個問題,我花費了很長時間測試,結果仍然一樣
各位先進們之前對於oldval(),curval()有三篇文章,我看了經過實際測試還是一樣
不知道我哪裡弄錯了,
所以就打擾各位,請各位前輩指導我,麻煩各位了
在此先向你們說聲 謝謝 |
|
回頂端 |
|
|
catjoke
註冊時間: 2003-06-16 文章: 175 來自: 香港
第 2 樓
|
發表於: 星期四 六月 10, 2004 5:53 pm 文章主題: |
|
|
OldVal() & EVAL()
記著不要做 TABLEUPDATE()
以及不要用 BUFFER 3, 因為 recno() 一走就存檔了.. _________________ 喵喎~ 貓當然是 "茅" 的嘛! ^0^; |
|
回頂端 |
|
|
syntech
註冊時間: 2003-05-16 文章: 4212 來自: Taipei,Taiwan
第 3 樓
|
發表於: 星期四 六月 10, 2004 5:56 pm 文章主題: |
|
|
你的實驗是對的,
但是.......
oldval()及curval()是指目前client 端的old value 及 current value,
並非 SQL server 上的欄位值
等到存檔時
vfp 會組合如下方的 sql command 到後端執行:
UPDATE 銷貨單 SET saleprice = curval() where trano='XXXX' and saleprice=oldval()
SQL SERVER這時才會檢查
如果發現找不到可更新記錄,就表示"記錄已被其他使用者修改" _________________ 如果公司有下列困擾:
1. 找不到便宜,快速,簡易的 生產排程軟體
2. 不知道如何快速排定 採購計劃
3. 成本抓不準,自己算比軟體算有用
4. 想學習系統規劃,想找系統架構的顧問
請聯絡我們,也許我們幫得上忙 |
|
回頂端 |
|
|
syntech
註冊時間: 2003-05-16 文章: 4212 來自: Taipei,Taiwan
第 4 樓
|
發表於: 星期四 六月 10, 2004 6:18 pm 文章主題: |
|
|
curval() 的說明提到 value 和 curval() 不一致的原因
Note If you are working with a view in a multiuser environment, the values returned by CURVAL( ) might not be up to date unless you call the REFRESH( ) function first. Data returned by a view is buffered, and the CURVAL( ) function reads values from the buffer. However, if other users have changed data in the underlying tables for the view, the buffered data is not updated until the REFRESH( ) function is called _________________ 如果公司有下列困擾:
1. 找不到便宜,快速,簡易的 生產排程軟體
2. 不知道如何快速排定 採購計劃
3. 成本抓不準,自己算比軟體算有用
4. 想學習系統規劃,想找系統架構的顧問
請聯絡我們,也許我們幫得上忙 |
|
回頂端 |
|
|
jasonyummy
註冊時間: 2004-05-06 文章: 15
第 5 樓
|
發表於: 星期五 六月 11, 2004 10:14 am 文章主題: |
|
|
照你的意思是說
目前要判斷是否有人先一步更改 SQL 值時,
只能在發生存檔失敗 ERROR=1585 ,然後自己到SQL取值來判斷是哪個欄位
已經被更改,及更改成何值.
然道沒有比較好的方法嗎?
謝謝指教 |
|
回頂端 |
|
|
goto-dream
註冊時間: 2004-05-11 文章: 909
第 6 樓
|
|
回頂端 |
|
|
jasonyummy
註冊時間: 2004-05-06 文章: 15
第 7 樓
|
發表於: 星期五 六月 11, 2004 3:02 pm 文章主題: |
|
|
謝謝
我可能要墊高枕頭好好的想一想 |
|
回頂端 |
|
|
jasonyummy
註冊時間: 2004-05-06 文章: 15
第 8 樓
|
發表於: 星期一 六月 14, 2004 2:54 pm 文章主題: |
|
|
哈!
我用一個方法, 不用自己寫函數也能得到我想要的, 雖然不滿意,但是還能接受
做法:
不要用全部更新的方法,用一筆一筆存的方式---
[ 用 tableupdate(.F.,.F.) ,不要用 tableupdate(.T.,.F.) ]
然後若有發生 1585 錯誤時,提出訊息告訴使用者[資料有更動,是否覆蓋,不更動,或取消存檔](若想要完美些,可以在這個時候讀取SQL的資料判斷哪些值有變動)
1.選擇覆蓋的話,則在最後面,再作一次 Tableupdate(.T,.T.)即可
2.若是選擇不更動的話,則用 Tablerevert(.F.)回覆一筆資料,仍然在最後面作一次Tableupdate(.T,.T.)
3.選擇不存檔的話,則返回,該復原緩衝的復原,若要回覆未修正時的資料用Tablerevert(.T.), 反則不要作
用GETNEXTMODIFIED(0)來判斷更動資料, 會有不正確的問題(若有覆蓋與不更動同時進行時)
所以我才用一筆一筆的存來彌補這個問題.
以上是我參考VFP說明檔內的 第十七章:共同存取之程式設計
加以測試, 然後取沒有問題的方法得到的, 你們可以去看看.
最後結語:
當然有許多細節要注意, 不過怕在關老爺面前耍大刀,貽笑大方,
一方面又想要讓這篇有頭有尾, 比較像樣些.所以就簡簡單單作個結尾,
謝謝大家 |
|
回頂端 |
|
|
syntech
註冊時間: 2003-05-16 文章: 4212 來自: Taipei,Taiwan
第 9 樓
|
發表於: 星期一 六月 14, 2004 3:18 pm 文章主題: |
|
|
猛一看,怎麼覺得是手冊上的作法,
原來真的是....
前面有關CURVAL()的說法不太對,
有時間再改一下.
CURVAL()手冊是說"現在在TABLE上的值",
可是SPT時,能不能拿不到"現在在TABLE上的值",
無論如何 ,不是
UPDATE 銷貨單 SET saleprice = curval() where trano='XXXX' and saleprice=oldval()
而是
UPDATE 銷貨單 SET saleprice = 'field value' where trano='XXXX' and saleprice=oldval()
遇到更新衝突時,才利用 CURVAL()判斷.
遇到更新衝突的作法,
每家公司的策略都不同,
我看過有家軟體公司的系統是不管有沒有衝突,
都由"後來存檔"的記錄為記錄,
即使這些記錄是過時的.
逐筆處理也是一種方法.
可是實務上卻應該以'整張單據'的處理來看,
這一整張單據只要有一筆失敗就應該是為整張都失敗,
才不會發生總計項目(也許放在表頭)與表身明細不一致的情況.
我在設定更新衝突的做法時,
是使用 更新衝突->提出警告並放棄->重新取得資料->編輯->再次更新
有的時候,使用者會面臨非得放棄一堆剛剛才打資料不可,
針對這點,我控制一次處理一張單據為原則,
編輯只能編輯一張單據,
所以存檔也是一張,放棄也是一張,
代價不會太高.
如果一張單據也會更新衝突,表示該公司事權不一致,也說的過去,
畢竟同一張單據不應該於同一時間由不同的人編輯
如何處理更新衝突是一門專業的學問,
應該花時間好好研究. _________________ 如果公司有下列困擾:
1. 找不到便宜,快速,簡易的 生產排程軟體
2. 不知道如何快速排定 採購計劃
3. 成本抓不準,自己算比軟體算有用
4. 想學習系統規劃,想找系統架構的顧問
請聯絡我們,也許我們幫得上忙 |
|
回頂端 |
|
|
|
|
您 無法 在這個版面發表文章 您 無法 在這個版面回覆文章 您 無法 在這個版面編輯文章 您 無法 在這個版面刪除文章 您 無法 在這個版面進行投票 您 無法 在這個版面附加檔案 您 無法 在這個版面下載檔案
|
|