亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

悠哉悠哉,一個復合查詢方法

2019-11-18 20:50:50
字體:
來源:轉載
供稿:網友
幾乎每個完整的應用程序都會需要一個復合查詢。建立一個功能強大的復合查詢首先必須要能夠動態生成查詢條件,其次應該能夠對查詢到的數據進行修改,最后這個復合查詢最好能夠對一對多的兩個表建立條件進行查詢。

在VFP里建立查詢的方法主要有這么幾種:一是使用VFP中自帶的SearchClass類;二是建立一個查詢;三是建立一個視圖,其中包括參數化視圖、宏替換Sql語句視圖;四是建立一個Grid,將其數據源設置為SQL語句或臨時表。

不管哪一種方法,其實質都是使用SQL語句。

這幾種方法各有各的優點,也都有缺點。

建立查詢的方法最死板,只能建立固定條件的查詢,并且不能更新數據,最不能滿足要求。

SearchClass類功能強大,但是它只能對一個表建立條件進行查詢,并且它的源代碼太復雜了,幾乎難以進行修改定制;(初學者想必都有過用表單向導建立表單后試圖修改txtbtn類、SearchClass類的經歷吧!看到源代碼后有幾個沒昏倒?)用將Grid的數據源設置為SQL語句或臨時表的方法無法修改/更新數據,刷新數據也比較困難。(這方面的問題在網易虛擬社區VFP版上有過許多討論,大家可以去看看。)建立視圖的方法中,參數化視圖也太簡單。不管是用表單控件的值作參數還是用給參數兩端加上引號的方法都只能對固定的字段進行查詢。如果是復合查詢,難道要先建立幾十個視圖嗎?最有前途的辦法還是用宏替換SQL語句建立視圖的辦法。視圖有著能夠對數據進行修改/更新的優點,如果能夠動態生成查詢條件,那么就是最完美的查詢了。建立宏替換sql語句視圖的具體辦法是先動態生成一個Sql語句sqlstatement,然后用宏替換的方法使用Create Sql view viewname as &sqlstatement來動態建立視圖,最后將數據動態顯示在一個Grid控件中??吹竭@里,VFP大蝦們怕會大喊:Stop!你當我是菜鳥啊!你的辦法從理論上雖然行的通,但實際做起來就會碰到查詢結果在表格上數據無法刷新的難題。俺早就試過不行了!你想騙稿費啊!嘿嘿,這個難題偏偏給我解決了!這就是我洋洋得意的寫這篇文章的原因!問題的解決

幾個月前(好可憐^0^.....),我參照VFP的Sample中的Solution里的Interactively Bulid a sql

statement示例建立了一個復合查詢,想將它集成到我自己的程序中。由于該示例是用browse窗口來顯示查詢結果的,而我自己的應用程序使用了頂層表單,結果編譯后運行才發現Browse窗口在頂層表單中無法顯示。于是我建立了一個有兩個表單的表單集,用一個表單makesql動態生成sql語句,在另一個表單form1上用grid來顯示查詢結果的數據,在給Grid設置數據源的時候,問題來了。首先使用臨時表來作為表格的數據源,結果第一次查詢正確,更改條件進行第二次查詢時碰到了眾所周知的"不能更新臨時表"的錯誤;使用sql語句倒是可以,可是在表格顯示數據前會莫名其妙的先出現一個Browse窗口,必須關閉它后才會顯示表格,由于browse窗口在使用頂層表單的程序中無法顯示,結果導致程序無法繼續執行,這個辦法也不行。

最后只能使用Create sql view viewname as &sqlstatement的辦法了,先隨便建立一個視圖tempview,把表格的Recordsourcetype屬性設置為1-別名,Recordsource屬性設置為視圖別名tempview,

在表單makesql上建立sql語句后的代碼中使用create sql view temp view as &sqlstatement建立視圖Tempview.

執行后發現,第一次查詢正確,更改查詢條件后再次查詢,出現"視圖已存在,要改寫嗎?"的情況,按下"確定"后,出現的表格中沒有數據。

避免出現對話框的問題好解決,在建立視圖前先用rename view tempview to oldview,然后用Delete view oldview將舊的視圖刪除就可以了。代碼如下:



set database to databasename &&databasename是你的數據庫名稱

&&注意:即使你打開了數據庫也必須寫這個語句!否則會出現"找不到數據庫"的錯誤。

if used("tempview")

rename view tempview to oldview

delete view oldview

endif

Create sql view tempview as &sqlstatement

=requery()

IF _TALLY = 0

#DEFINE MSG_LOC "沒有找到符合條件的紀錄!"

#DEFINE TITLE_LOC "沒有找到紀錄"

=MESSAGEBOX(MSG_LOC,64+0+0,TITLE_LOC)

ELSE

thisform.hide

thisformset.form1.show

Endif

*****************************************************************************

但是這樣做了以后,表格上沒有數據的問題仍然存在。查找資料后發現,用Create sql view語句編

程建立視圖的方法,建立視圖后要先保存視圖定義,再打開視圖后視圖中才有數據。因此,必須將Creat

sql view語句部分代碼修改如下:

************************************************

Create sql view tempview as &sqlstatement

use

use tempview

************************************************

滿以為這下問題解決了,結果更慘。出現的表格上不但沒有數據,連表頭、網格都不見了!這個問題

百思不得其解,查找資料也沒有結果,最后不了了之,一直困擾了我幾個月。

就在昨晚,我上床的時候突然靈光一現:既然表格無法動態加載數據源視圖,那么干脆連包含表格的

表單也動態生成!只要表單動態生成,那么表單上的表格對象的數據源不就完全重新加載了嗎?也用不著刷新什么的了!而且,用這個方法也用不著先建立一個tempview視圖,完全在程序中動態生成就可以了主意一定,馬上下床動手。將原來包含表格的表單form1刪除,在上述的代碼中最后一句

thisformset.form1.show前插入以下代碼:

*************************************************************

thisformset.addobject("form1","form")

with thisformset.form1

.caption="查詢結果"

.width=600

.height=400

.Autocenter=.t.

.controlbox=.f.

endwith

thisformset.form1.addobject("cmdReturn1","cmdReturn")

with thisformset.form1.cmdReturn1

.top=360

.left=270

endwith

thisformset.form1.addobject("grid1","gird")

with thisformset.form1.grid1

.Recordsourcetype=1

.Recordsource="tempview"

.top=10

.left=20

.height=300

.width=560

endwith

**************************************************************

在程序的最后加入:

*********************************************

Define class cmdReturn as commandbutton

caption="返回"

PRocdure click

thisform.release

endproc

enddefine

*********************************************

這下總可以了吧?運行程序,結果出現對話框"在事件或方法中不能嵌套類定義!"。我@#$%&*....什么嘛!教科書、幫助文件中的示例prg都是這么寫的??!
不過好在還有辦法,我手工建立一個類總行了吧!在類庫mybut中新建一個按鈕類cmdReturn,設置它的cation屬性為"返回",click事件代碼為
thisform.release。在上面的代碼前插入set Classlib to mybut additive(注意:如果不加additive參數,將關閉所有之前打開的類庫?。?,然后將最后的類定義語句Define...EndDefine全部刪除。運行,新表單出現!且慢,這個表單上怎么什么東西都沒有?:-((打開調試器,在"局部"窗口中察看,發現明明有cmdReturn1、Grid1對象?。≡趺椿厥??仔細察看他們的每個屬性,發現原來它們的visible屬性都為false!原來,我們平常看到的幫助中的示例都是prg文件,在這些文件中用addobject()方法向表單添加的對象在顯示表單后都是可見的。而在表單的scx文件中使用addobject()方法建立的任何東西,其visible屬性都為false!本質上,用createobject()、addobject()方法建立的對象,其實只是在內存中建立了一個對象變量,必須再用語句使它們實例化。比如,我們常用的mainform.show語句就是如此,沒有使用show方法,mainform就只是內存中的一個變量,而不是一個表單不可見的實例!反之,thisform.release語句則從根本
上釋放了表單上所有的對象變量,從而在內存中完全清除了表單.而在prg文件中與scx文件中用addobject()方法建立表單和控件的順序是不一樣的,在prg文件中是先向表單添加控件再顯示表單,表單上的控件繼承了表單的visible屬性,當表單實例化時控件也實例化;而在scx文件使用addobject()方法是先顯示表單,然后再向表單添加控件的,因此必須手工設置控件的visible屬性為Ture。

當然這樣比較麻煩,干脆在mybut類庫中手工建立一個Resultform表單類,在該表單類上添加一個命令按鈕cmdReturn和一個Grid1,設置命令按鈕cmdReturn的caption屬性為"返回",Click事件代碼為thisform.release,設置Grid1的RecordSourceType屬性為1-別名,RecordSource屬性為Tempview,這樣就
不用在代碼中手工輸入thisformset.form1.cmdReturn1.visible=.t.語句,省事多了。

最終的程序代碼如下:

*******************************************************

set database to databasename

 

if used("tempview")

rename view tempview to oldview

delete view oldview

endif

 

Create sql view tempview as &sqlstatement

=requery()

IF _TALLY = 0

#DEFINE MSG_LOC "沒有找到符合條件的紀錄!"

#DEFINE TITLE_LOC "沒有找到紀錄"

=MESSAGEBOX(MSG_LOC,64+0+0,TITLE_LOC)

ELSE

set Classlib to mybut additive

thisformset.addobject("form1","Resultform")

thisform.hide

thisformset.form1.show

Endif

********************************************************

運行程序,一切ok!終于實現了動態生成查詢條件,動態顯示結果。只要再用dbsetprop()語句設置視圖為可更新,就能對查詢結果進行修改/更新了!這是我見到過的最完美的復合查詢了!就這么簡單?沒錯,就這么簡單!一個困擾數月的問題,研究的時候峰回路轉,最終結果卻是如此輕松!這就是編程的藝術吧!
這個問題的解決,雖然走了許多彎路,但是也讓我們了解了許多VFP的原理,難道不是很值得嗎?!光憑書本的知識,你永遠也無法了解這些東西的。有人說:讀三年的書,還不如寫一個月的程序,不是嗎?!其他:

我在本文中省略了開頭的動態生成sql語句的部分,具體的做法大家可以研究一下VFP自帶的示例應用程序solution中databases目錄下的view/queries目錄中的Interactively Bulid a sql statement示例,你甚至可以稍作修改就在你自己的程序中使用該表單。

我曾經就其原理寫了一篇文章《交互式建立sql復合查詢-vfp示例應用程序詳解》貼在網易虛擬社區VFP版,有興趣的朋友可以在精華區查到,讀完該篇文章,你應該可以自行修改該程序使之能夠對一對多數據庫進行查詢了。因為該文篇幅很長,又比較枯燥,就不在這兒解說了。

要注意的是:原示例程序用于生成sql語句查詢。要改為用于建立sql視圖,必須作一些修改:1、在sql查詢中不必限定表別名和數據庫名,而建立sql視圖卻必須這樣做。因此需要修改makesql表單的自定義方法bldsql的代碼,將源代碼下面的部分:

**************************************************************************

IF !EMPTY(lcOperand)

lcValue2 = THISFORM.ValidateType(THIS.cboField2.Value,lcValue2)

lcWHERE = lcOperand + " " + lcField2 + " " + ;

lcRelation2 + " " + lcValue2

ENDIF

** Create the first part of the WHERE condition

lcWHERE = "WHERE " + lcField1 + " " + lcRelation1 + " " + lcValue1 + " " + lcWHERE

 

** Create the full SQL command using the base table for the form

lcSQL = "SELECT * FROM " + lcAlias + " " + lcWHERE

****************************************************************************

修改為:

****************************************************************************

If !empty(lcOperand)

lcValue2 = thisform.ValidateType(this.cboField2.value,lcValue2)

lcWhere = lcOperand + " " + lcAlias + "." + lcField2 + " " +;

lcRelation2 + " " +lcValue2

Endif

lcWhere = "Where "+ lcAlias + "." + lcField1 + lcRelation1 + " ";

+ lcValue1 + " " + lcWhere

lcSql = "Select * From " + "DatabaseName!" + lcAlias + " " + lcWhere

****************************************************************************

DatabaseName是你的數據庫的名字。以上修改的實質是,給要查詢的字段名限定其所在的表別名,給

select form的表別名限定所屬的數據庫。

2、修改RunSql命令按鈕的Click事件代碼,將原代碼:

*************************************************************************

cMacro = ALLTRIM(THISFORM.edtSQL.Value) + "INTO CURSOR TEMPQUERY"

*************************************************************************

中的 (+ "INTO CURSOR TEMPQUERY")部分刪除,將cMacro改為sqlstatement.并將除了下面部分外的全

部代碼刪除:

*************************

IF USED(lcOldAlias)

SELECT (lcOldAlias)

ENDIF

*************************

,插入上面的最終代碼就可以了。

ok!現在所有的任務都完成了。做完所有的這一切,花不了十分鐘,你就建立了一個強大的復合查詢!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩av在线看| 日韩免费在线看| 久久成人精品视频| 亚洲国产精品资源| 亚洲男人的天堂在线| 国产精品成人一区二区三区吃奶| 国产午夜精品视频免费不卡69堂| 成人精品一区二区三区电影免费| 国产精品久久久久久久久借妻| 亚洲欧洲一区二区三区在线观看| 在线观看欧美www| 综合久久五月天| 91欧美精品午夜性色福利在线| 精品久久香蕉国产线看观看gif| 欧美日韩国产999| 日本一区二区不卡| 国产精品成av人在线视午夜片| 欧美日韩激情美女| 国产精品久久999| 久久国产精品99国产精| 国产日韩欧美夫妻视频在线观看| 亚洲午夜精品久久久久久久久久久久| 精品亚洲夜色av98在线观看| 国产黑人绿帽在线第一区| 91在线观看免费高清完整版在线观看| 精品视频久久久| 亚洲成av人影院在线观看| 欧美在线欧美在线| 亚洲老板91色精品久久| 成人黄在线观看| 日本不卡免费高清视频| 久久精品91久久久久久再现| 欧美激情综合亚洲一二区| 欧美性在线观看| 久久精品视频播放| 国产在线精品成人一区二区三区| 久久伊人精品天天| 国语自产精品视频在线看抢先版图片| 久久久国产精品一区| 精品国产乱码久久久久久婷婷| 亚洲天堂第二页| 国产精品视频一区国模私拍| 久久精品国产亚洲精品| 久久天天躁狠狠躁夜夜躁2014| 久久久久久国产精品久久| 亚洲香蕉伊综合在人在线视看| 国产精品色视频| 国产精品永久免费在线| 亚洲精品国产欧美| 国产亚洲激情在线| 久久久久久高潮国产精品视| 亚洲欧美另类中文字幕| 国产精品国产自产拍高清av水多| 欧美日韩午夜视频在线观看| 伊人久久综合97精品| 亚洲国产一区二区三区在线观看| 欧美激情在线有限公司| 国产精品9999| 国产欧美韩国高清| 国产在线a不卡| 欧美福利视频在线观看| 91国产视频在线播放| 91在线国产电影| 亚洲欧洲在线观看| 日韩国产欧美精品一区二区三区| 91久久久精品| 国产男人精品视频| 精品国产美女在线| 国产欧美va欧美va香蕉在| 91精品综合视频| 欧美激情一区二区三级高清视频| 中文字幕亚洲一区二区三区五十路| 国产美女直播视频一区| 日韩中文娱乐网| 黑人巨大精品欧美一区二区| 国产亚洲精品久久久优势| 九九精品在线视频| 成人淫片在线看| 欧美日韩激情美女| 亚洲系列中文字幕| 黄色成人在线播放| 一区二区三区视频免费| 国产精品网站入口| 亚洲美女在线观看| 最近中文字幕日韩精品| 亚洲成人网久久久| 国产91亚洲精品| 色偷偷综合社区| 欧美日韩国产精品一区二区不卡中文| 国产乱人伦真实精品视频| 欧美激情一区二区三区在线视频观看| 国产成人精品优优av| 91av在线精品| 亚州av一区二区| 亚洲人成电影网站色…| 久久av红桃一区二区小说| 亚洲精品久久久久久下一站| 国产精品尤物福利片在线观看| 91精品视频免费观看| 中文字幕免费精品一区| 日本久久久久久久久久久| 久久精品国产精品亚洲| 久久中文字幕在线视频| 在线观看日韩www视频免费| 中文字幕视频一区二区在线有码| 欧美色道久久88综合亚洲精品| 国产成人精品日本亚洲专区61| 亚洲国产高潮在线观看| 一区二区日韩精品| 亚洲影视中文字幕| 亚洲视频在线免费观看| 91精品视频播放| 久久久久国产精品免费网站| 9.1国产丝袜在线观看| 欧美自拍大量在线观看| 亚洲欧美在线一区二区| 日韩高清电影免费观看完整| 亚洲精品乱码久久久久久按摩观| 亚洲自拍小视频免费观看| 国产亚洲美女精品久久久| 在线观看不卡av| 国产精品久久久久高潮| 欧洲精品久久久| 欧美韩日一区二区| 久久99久久99精品中文字幕| 日韩中文字在线| 亚洲乱码国产乱码精品精天堂| 91久久精品久久国产性色也91| 国产精品自拍网| 亚洲人成电影网站| 欧美日韩中文字幕综合视频| 亚洲一区二区日本| 日韩精品一区二区视频| 91国产精品电影| 亚洲精品久久久久久久久久久久久| 免费91在线视频| 欧美日韩亚洲网| 久久久久国产精品免费| 久久国产精品久久精品| 66m—66摸成人免费视频| 黑人巨大精品欧美一区二区| 在线看欧美日韩| 国产精品久久久91| 国产精品美女av| 欧美一级高清免费播放| 国产精品成人品| 日本久久中文字幕| 欧美福利视频网站| 成人妇女淫片aaaa视频| 国产精品日韩在线播放| 国内精品免费午夜毛片| 国产在线日韩在线| 国产亚洲人成网站在线观看| 国产亚洲欧美日韩美女| 高清亚洲成在人网站天堂| 色噜噜亚洲精品中文字幕| 日韩精品丝袜在线| 91免费版网站入口| 国产精品成人免费视频| 91精品国产777在线观看| 日韩欧美亚洲国产一区| 国产精品高潮视频| 在线看片第一页欧美| 欧美又大又粗又长|