把資料集設為可更新
Visual FoxPro的游標類型
游標的英文稱呼是Cursor,在Visual FoxPro中習慣的提法是暫存資料表(Temp Table),不過我想應該根據慣例叫它游標。因為Visual FoxPro的游標絕對強勁,如果稱呼Temp Table恐造成誤會,好像Visual FoxPro不支援游標一樣。
Visual FoxPro的游標有三種:唯讀游標、可讀寫游標、可更新游標。
唯讀游標是那種不能被修改的游標,在Visual FoxPro中使用SQL-Select語句產生的游標就是典型的唯讀游標:
SELECT * FROM ORDERS INTO CURSOR MYCURSOR
對於結果集合MyCursor來說我們不能對它執行任何寫操作,如:Replace、Delete、Update等。
可讀寫游標是那種可以進行讀寫操作,但游標上的資料變更不被反映到資料來源的游標:
典型的可讀寫游標有三類,其一就是用SQLEXEC()得到的游標,我們可以對它進行各種操作(從了Zap、Pack這樣的表壓縮命令),但是任何資料的變動都不會反映到資料來源。
第二類可讀寫游標是Visual FoxPro 7 的新特性,我們在SQL-Select語句上加入關鍵字readwrite就可以得到這種游標。這是一個非常棒的特性,有了它在Visual FoxPro中操作中間結果就更自由了:
SELECT * FROM ORDERS INTO CURSOR MYCURSOR READWRITE
第三類可讀寫游標是“沒有設定發送更新”的本地視圖和遠程視圖。
記得我在“遠程視圖”一章裡反覆強調:要想視圖是可更新的就必須設定它的SendUpdate屬性為.t.,如果沒有設,試圖就是可讀寫游標了,任何對視圖資料的操作都不能反映到資料來源裡了。
可更新游標是那種可以進行讀寫操作,並且任何資料變動都會反映到資料來源的游標:
典型的可更新游標就是可更新視圖,對它的好處我就不多加議論了,因為詳細的內容在“遠程視圖”一章裡已經討論過了。
把SQLEXEC()得到的結果集設定為可更新游標的五大步驟
在“遠程視圖”一章裡我就反覆強調,Visual FoxPro是怎麼產生語句SQL描述,發送到SQL Server中去的。大家可以想象配置一條SQL-Update或是SQL-Insert或是SQL-Delete需要的要素,怎樣把用戶端變動轉化為SQL語句需要的東西,就是我們要設定的東西:
A.CURSORSETPROP("TABLES",資料來源表名,可更新游標名)
此步驟設定的是資料來源裡(SQL Server)待更新的表名,如果涉及多個表就這樣寫:CURSORSETPROP("TABLES","T1,T2","MyCursor")。
B.CURSORSETPROP("KEYFIELDLIST",關鍵字段,可更新游標名)
此步驟是設定關鍵字段的,這個關鍵字段是這可更新游標的欄位,而不是資料來源裡欄位。
C.CURSORSETPROP("UPDATABLEFIELDLIST",可更新欄位列表,可更新游標名)
此步驟設定的是在可更新游標裡哪些欄位的變動要被反映到資料來源,即哪些欄位時可更新的。
D.CURSORSETPROP("UPDATENAMELIST",前後段欄位對應關係列表,可更新游標名)
此步驟設定前後端欄位的對應關係。
E.CURSORSETPROP("SENDUPDATES",.T.,可更新游標名)
這個步驟就不應多說了,最關鍵的一步,不做的話前面的努力都白搭。
下面我用三個執行個體來說明問題:
例一:
cnn=SQLCONNECT("northwind")
SQLEXEC(cnn,"select categoryid as id ,categoryname,description from categories","mycursor")
SELECT mycursor
CURSORSETPROP("Tables","categories","mycursor")
CURSORSETPROP("KeyFieldList","id","mycursor")
CURSORSETPROP("UpdatableFieldList" ,"id,categoryname,description","mycursor")
CURSORSETPROP("UpdateNameList","id categories.categoryid,categoryname categories.categoryname,"+;
"description categories.description","mycursor")
CURSORSETPROP("SendUpdates" ,.t.,"mycursor")
-
資料來源表是 NorthWind 資料庫的Categories 表,可更新光表是mycursor
-
CURSORSETPROP("Tables","categories","mycursor"),TABLES屬性設定的是:被更新的資料來源表Gategories
-
CURSORSETPROP("KeyFieldList","id","mycursor"),關鍵字用可更新游標的欄位名:ID,而不是資料來源表的欄位名:categoryid
-
CURSORSETPROP("UpdatableFieldList" ,"id,categoryname,description","mycursor"),可更新欄位列表都用可更新游標的欄位名表示,而不是資料來源表的欄位名。
-
CURSORSETPROP("UpdateNameList","id categories.categoryid,categoryname categories.categoryname,description categories.description","mycursor"),請注意這裡的寫法:每一組對應關係用逗號分開,前面寫可更新游標的欄位名,再放置一個空格,接著寫資料來源表的欄位名(注意一定要加上資料來源表名稱)
例二
cnn=SQLCONNECT("northwind")
SQLEXEC(cnn,"select a.productid,a.productname,a.unitprice,b.categoryid,b.categoryname,c.supplierid,"+;
"c.companyname as suppliername,c.contactname"+;
" from (products a inner join categories b on a.categoryid=b.categoryid)"+;
" inner join suppliers c on a.supplierid=c.supplierid","mycursor")
SELECT mycursor
CURSORSETPROP("Tables","products,categories,suppliers","mycursor")
CURSORSETPROP("KeyFieldList","productid,categoryid,supplierid","mycursor")
CURSORSETPROP("UpdatableFieldList",+;????????????????????? "productid,productname,unitprice,categoryid,categoryname,supplierid,suppliername,contactname","mycursor")
CURSORSETPROP("UpdateNameList","productid products.productid,productname ,"+;
"products.productname,unitprice products.unitprice,"+;
"categoryid categories.categoryid,categoryname categories.categoryname,"+;
"supplierid suppliers.supplierid,suppliername suppliers.companyname,contactname suppliers.contactname","mycursor")
CURSORSETPROP("SendUpdates" ,.t.,"mycursor")
-
這是一個三個表(Categories,Products,Suppliers)的串連結果集合,算是複雜了,我們的目標就是使所有的欄位都能更新到相應的表中。
-
注意“Tables”屬性的寫法,涉及三個表就羅列三個表!
-
注意“KeyFieldList”屬性的寫法,三個表的關鍵字都要列上。如果你沒有把supplierid了如的話,那麼來自於suppliers表的欄位就無法更新到suppliers表中了。
例三
cnn=SQLCONNECT("northwind")
SQLEXEC(cnn,"select orderid,productid,unitprice,quantity,discount from [order details]","mycursor")
SELECT mycursor
CURSORSETPROP("Tables","[order details]","mycursor")
CURSORSETPROP("KeyFieldList","orderid,productid","mycursor")
CURSORSETPROP("UpdatableFieldList" ,"orderid,unitprice,quantity,discount","mycursor")
CURSORSETPROP("UpdateNameList","orderid [order details].orderid,unitprice [order details].unitprice,quantity [order details].quantity,discount [order details].discount","mycursor")
CURSORSETPROP("SendUpdates" ,.t.,"mycursor")
-
這個結果集來自於一個表:Order Details。
-
注意“Tables”屬性的寫法,在SQL Server中這種帶空格的表名請用方口號分隔,Tables屬性指定的是資料來源表,所以必須用:[order details]填入。
-
注意“KeyFieldList”屬性的寫法,這個order details表的主關鍵字是一個複合關鍵字,有orderid與productid聯合組成,所以這裡就要將他們一起填入。
一個很重要的屬性——WhereType
當我們設定結果集為可更新游標後,還有一個重要的屬性沒有設定,就是WhereType。即,Where字句產生的依據,有四種情況:
CURSORSETPROP("WhereType" ,1) &&根據關鍵字
CURSORSETPROP("WhereType" ,2) &&根據關鍵字+可更新欄位
CURSORSETPROP("WhereType" ,3) &&根據關鍵字+已更新欄位
CURSORSETPROP("WhereType" ,4) &&根據關鍵字+時間戳記
更詳細的內容大家可以參看“遠程視圖”章節,在那裡面我已經講得很多了。