正文

SQL语言详解 2005-11-13 10:10:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/wondgergis/6795.html

分享到:

 

Visual FoxPro的诸多特色之一便是结构化查询语言(Structured Query Language)。SQL此一语言提供了用来建立、维护几查询一个关系数据库管理系统的命令。

1.SQL的SELECT命令

SQL有许多重要的层面,但是其语言的核心则依靠数据查询与查询结果的快速回报。对某些使用者而言,他很可能仅使用到SQL此一层面。在SQL中,所有的查询(Query)操作完全由SELECT命令独立完成。

SELECT是一个用来从一个或一个以上的表获取数据的SQL命令。当您使用SELECT命令进行一个查询时,Visual FoxPro会解译此查询并从表中获取指定的数据。SELECT命令叙述可简可繁,命令行的长度依据查询的复杂度而定。它能够包含数据字段、常数值、内存变量、运算式、函数或宏。然而,SQL的SELECT终究还是一个命令,因此其单一命令叙述最长不可超过8192个符号。而任何使用在SELECT命令中的宏替换最大亦不可超过8192个符号。

或许有人会问,此SELECT命令不是与切换工作区用的SELECT命令相同吗?关于此点您大可放心,因为Visual FoxPro不仅是快速,它更是聪明,它会自动分辨您所使用的究竟是SQL之SELECT或是切换工作区的SELECT。

SQL之SELECT命令的语法如下:

SELECT[ALL DISTINCT] [TOP nExpr [PERCENT]]
[Alias.] Select_Item [AS Column_Name]
[,[Alias.] Select_Item [AS Column_name]…]
FROM [FORCE]
[DatabaseName!]Table[[AS]Local_Alias]
[[INNer LEFT[OUTER] RIGHT[OUTER] FULL [OUTER]JOIN
DatabaseName!]Table[[AS] Local_Alias]
[ON JoinCondition…]
[[INTO Destination]
[TO FILE FileName [ADDITIVE] TO PRINTER [PROMPT]
TO SCREEN]]
[PREFERENCE PreferenceName]
[NOCONSOLE]
[PLAIN]
[NOWAIT]
[WHERE JoinCondition [AND JoinConditiion…]
[ AND OR FilterCondition [AND OR FilterCondition…]]]
[GROUP BY GroupColumn [, GroupColumn…]]
[HAVING FilterCondition]
[UNION [ALL] SELECTCommand]
[ORDER BY Order_Item [ASC Desc][,Order_Item [ASC DESC]…]]

此命令的使用方式与其它 Visual FoxPro 之内建立指令相同。您可以于命令的视窗、程序或事件程序中使用此命令。

于使用SQL前,您必须先了解一些专业的术语。如下所示:

一个表中的各列(rows)与一个表中的各笔数据纪录相同。当我们讨论查询的输出结果时,将会使用到表(TABLE)、列(rows)及行(Columns)三个名词。

2.简易的SELECT查询

请显示出表employee中,所有员工的身份证字号、姓名与联络电话。

*采用SQL命令的解答如下:
CLEAR ALL
SELECT uid,name,home_tel;
FROM employee;
INTO CURSOR temp

*采用程序化命令的解答如下:
CLEAR ALL
USE employee
COPY TO tmp EIELDS uid,name,home_tel

由命令语法可以了解到,SELECT命令拥有非常多可选择型性的参数,而上面所示范者,是最简易的SELECT查询。SELECT命令至少必须包含下列两个参数:

将来要出现在查询结果的数据字段的字段串列,即语法中的Select_Item。您最多可选取255个字段个字段。

这些字段来自哪些表,即FROM之后的Table参数。


事实上SELECT命令的字段串列中各个字段的先后次序也就是这些字段出现在查询结果中先后次序。以本例而言,如果您希望字段出现在查询结果中的次序是:name home_tel uid,则可将SELECT命令改写如下:

SELECT name,home_tel,uid FROM employee

我们可以说Select_Item代表查询结果中的一个列。此Select_Item可以是FROM参数所制定表中的一个字段、一个常数值、一个运算式或是一个使用者自定函数。而且当Select_Item是一个字段或一个包含字段的运算式时,还可以搭配内储函数使用。在此还要特别说明一点,如果您要查询初所有的字段,不须一一列出所有字段的名称,只需使用一个星号(*)即可,因为在SQL的标准中,星号(*)是一个统配符,其意为所有的字段。以下面的命令叙述而言,表示查询出表employee所有字段的内容:

SELECT * FROM employee

您可以指定SELECT命令的查询结果要输入至何处。在预设状态下,查询结果讲述处置BROWSE视窗,但是加入您希望将查询结果输出至BROWSE视窗以便能立即看到查询结果,要不加上INTO CURSOR参数即可。

FROM参数能够告知有哪些表会在SELECT命令查询的过程中使用。以本例而言,表employee将会被使用。您必须了解的是,SELECT会先确认FROM参数所指定的表是否已经打开,假如此表尚未打开,SELECT会自动在未被选取的最低号工作区中打开此表;反之,假如此表已打开,SELECT将不再打开。注意:

在网络的环境下,SELECT命令是否依专用模式打开FROM参数所指定的表将由SET EXCLUSIVE命令决定。

您务必记得,SELECT命令虽然会自动打开表,但是查询完毕后他并不会自动将表关闭。

如果于执行一个SELECT命令时TALK被设定成ON(即SET TALK ON),则Visual Foxpro会在状态行显示出此查询所花费的时间,以及查询结果中的记录笔数。


值得注意的是,如果您于FROM参数中所指定的表并非是作用数据库中的表,请务必于表的名称前加上所属数据库的名称与一个惊叹号,如:

SELECT 身份证字号,员工姓名,电话号码 FROM Demodbc7!Foxman
*表示要查询数据库Demodbc7 中的表Foxman

3.AS参数的使用

请显示出表employee中,所有员工的姓名、家庭地址及联络电话,不过请使用较易让使用者了解的文字作为列的标题。本查询需求的解答有下列两种:

*采用SQL命令的解答如下:
CLEAR ALL
SELECT name AS 姓名,address AS 家庭地址,home_tel AS 联络电话:
FORM employee

*采用程序化命令的解答如下:
CLEAR ALL
USE employee
BROWSE FIELDS name :H="姓名",;
Address : H=“家庭地址”,;
Home_tel: H=“联络电话”

AS 参数属于字段层级的参数,它让使用者能自行设定列的标题。大家要小心的是,请不要在AS参数所指定的列标题文字前后加上引号。事实上查询结果的各个列的标题是依下列优先顺序来决定的:

如果您使用了AS参数,则列标题将是AS参数所指定的文字。

如果您并未使用AS参数,但是曾经于表设计工具中替字段定义字段标题,则此字段标题将成为列的标题。

如果您并未使用AS参数,且未曾于表设计工具中替字段定义字段标题,则此字段的名称将成为列的标题。


请注意:

一旦您使用AS参数指定了列的标题,而且您是将查询结果输出至一个表或虚拟暂存表中,则此一表或虚拟暂存表之各个字段的名称将是相对应之AS参数所指定的列标题。以下面的命令叙述而言,test.dbf中之字段名称的将是“姓名”而不是name:
SELECT name AS 姓名 FROM 3employee INTO TABLE test

如果您并未使用AS参数,但是曾经于表设计工具中替字段定义字段标题,并将查询结果输出至一个表或虚拟暂存表中,则此一表或虚拟暂存表之各个字段的名称仍旧是来源表之各个字段的名称,不会是字段标题。


4. 关键字 ALL 与 DISTINCT 的使用

请显示出表employee中所有员工的雇佣日期,但是日期相同者只要显示一次即可。本查询需求的解答有下列两种:


*采用SQL命令的解答如下:
CLEAR ALL
SELECT DISTINCT hire_date;
FROM emloyee;
INTO CURSOR tmp

*采用程序化命令的解答如下:
CLEAR ALL
USE employee
INDEX ON hire_date TAG Uhire_date UNIQUE
COPY TO tmp FIELDS hire_date

预设状况下,所有的数据记录都会被显示出来。但如果您不想显示重复的数据记录(亦即若有多笔相同的数据记录时,只要显示其中一笔),请加入关键字DISTINCT。不过请记得,每一道SELECT命令仅能拥有一个DISTINCT关键字。

但是大家必须注意,事实上当数据记录越多,SELECT…DISTINCT的速度就越底。这是因为它必须进行更多的比较,更惨的是,它无法利用既存的索引来比较。所以当数据记录非常多时,除非真的确定不要显示重复的列,否则请勿使用关键字DISTINCT。

即使如此,关键字DISTINCT在某些查询需求中确实能帮助使用者轻易取得所需的数据。比方说,您想要知道表employee记载了哪些部门的员工数据,只需执行下列的查询命令即可:

SELECT DISTINCT depatrment FROM employee

5. 查询结果输出地

在预设状态下,SQL SELECT的查询结果会被输出至BROWSE视窗。但是面对众多程序设计师而言,他们可能更希望将查询结果输出至一储存处以便进行更进一步的处理。事实上,利用INTO参数便可将查询结果输出至一个数组(Array)、虚拟暂存表(Cusor)或是一个真实表(Table)中。

此外,您亦可利用TO参数将查询结果输出至一个ASCII文本文件、打印机或是直接输出于屏幕画面。但是,假如您同时使用INTO与TO参数,则TO参数将会被忽略。

INTO ARRAY ArrayName
于SQL SELECT命令叙述中加入INTO ARRAY ArrayName参数,表示将查询结果储存至ArrayName参数所指定的变量数组中。例如:

SELECT * FROM employee INTO ARRAY myary

表示将表employee中所有的数据纪录存入数组myary中。而且我们可以发现,用来存放查询结果的数组无须事先建立,因为SELECT命令会自动建立此数组。注意:

1. 如果SELECT命令叙述没有产生任何查询结果,亦即查询结果中的数据纪录数目是0,数据将不会自动被建立。因此如果后续的程序代码会进行数组读取动作的话,请务必先判断此数组是否存在。由于系统内存变量_TALLY会记载有多少笔数据记录出现在查询结果中,因此当您想在程序中去测知有多少笔数据记录符合查询的过滤条件,只要去读取_TALLY即可。由此可知,我们可以这样编写代码:

。。。
。。。
SELECT 。。。 INTO ARRAY storage

IF _TALLY=0 &&表示数组没有被建立
WAIT WINDOW “没有任何符合查询过滤条件的数据记录” NOWAIT
RETURN

ELSE


。。。
<处理数组之程序代码>
。。。
ENDIF

2. 数组的大小是有限的。因此再将查询结果之如数组前,请确定查询结果的数组两的大小不会超过数组所能符合的极限。在Visual FoxPro中,一个数组最多能拥有65,000个元素。


INTO DBF | TABLE TAB | eNAME [DATABASE DatabaseName [NAME Long TAB | Ename ] ]

如果您希望将查询结果储存至TABLE参数所指定名称的表文件中,请于SQL SELECT 命令叙述中加入INTO DBF或INTO TABLE参数。

如果您所指定的表文件已经打开,Visual FoxPro会关闭此表文件并且不经警告便重新建立一个新的表文件(如果SAFETY 被设定成OFF——SET SAFETY OFF)。而且除非您自行指定后缀名,否则此表文件之后缀名为 .DBF。于SELECT被执行后,此表文件便努被打开并成为作用表。例如:

SELECT name,address FROM employee INTO TABLE test

注意:

在网络环境下,Visual FoxPro再将查询结果储存至您于INTO TABLE DBF参数所指定的表文件后,会立即依专用模式将它打开,且不管SET EXCUSIVE命令设定为何。

在网络的环境下,如何利用into table dbf参数中所建立的表文件只是做暂存之用,请使用RIGHT(SYS(2015),8)产生一唯一文件名乘坐为此暂存表文件的名称,以避免程序同时执行时数据彼此覆盖。例如:

tmpdbf=RIGHT(SYS(2015),8)
SELECT * FROM employee
INTO TABLE (tmpdbf)
。。。
。。。
USE IN (tmpdbf)
ERASE (tmpdbf)+“.DBF”


值得注意的是,INTO DBF或INTO TABLE参数所指定之用来存放查询结果的表文件将是一个独立存在的表文件(Free Table)——亦即它不隶属于任何一个数据库。 如果您希望将查询结果储存智谋一个数据库的表中,必须在利用DATABASE Database参数来指定数据库的名称,不过此一数据库必须已经存在,否则将发生错误。以下面的命令叙述而言,表示将查询结果储存至数据库TEMP的表test中:

SELECT * FROM employee INTO TABLE test DATABASE temp

一旦使用DATABASE DatabaseName 参数制订了数据库的名称,就可以再加上NAME LongTABLEName参数来指定表于数据库中的长名称。以下面的命令叙述而言,表示将查询结果储存之数据库TEMP的表test中,并以MediaTEMPTable作为表的长名称:

SELECT * FROM employee INTO TABLE test DATABASE temp MediaTEMPTable

INTO CURSOR CusorName [NOFILTER]

于SQL SELECT命令叙述中加入INTO CURSOR CursorName参数,表示将查询结果储存至CusorName参数所指定名称的虚拟暂存表中。在SQL中,所谓的“CURSOR”指的是一个虚拟暂存表。不过请大家注意,CursorName参数所指定的虚拟暂存表的名称不能够与一个已经打开之表的别名相同,此外,虚拟暂存表名称也不能以数字开头,若发生这两种情况之一,将会造成错误。

事实上严格说起来,利用 INTO CURSOR CusorName所指定的虚拟暂存表(以下简称Cursor)并不是表。因为根据内存的容量于是用于SELECT 命令中的参数,很可能几乎所有的时间Cursor皆仅存在于内存之中,他们甚至根本从未在磁盘上出现过。正由于此项特点,Cursor被建立及被取用时的速度要比正常的表快上许多。注意:假如内存无法完全容下Cusors,Cusors会议暂存文件.TMP的形式存放在组态项目SORTWORK所指定的磁盘目录下。

一旦您是关闭表的命令(USE、USE IN、CLEAR ALL、CLOSE ALL、CLOSE TABLES与CLOSE DATABASE)来关闭Cursors,Cursors便随即永远消失,升值在文件俄删除操作上Cursors被删除的速度亦是最快的。基于以上理由,使用Cursors做为程序中的暂存表文件无疑是最恰当不过的了。

我们必须强调,在SELECT命令中加入INTO CURSOR参数所产生之Cursors是“只读”(Read-Only)的,亦即您不能对它进行任何写入的动作——包括新增、修改、删除、及编制索引。因此我们通常利用Cursors 来作为报表、更新一个真实表或浏览的数据来源。(在 Visual FoxPro 7.0 中 Cursor 可以设定为可读写)

在SELECT命令一被执行后,此虚拟暂存表便会被打开并成为作用表,但是究竟Cursors 会被打开与哪一个工作区中则无法测知,因此您只能使用Cursors 的别名来取用它。

如果您希望查询结果能永久的保存,则必须使用INTO DBF|TABLE TableName|将查询结果存入一个真实表文件中。

在一个复杂的数据库处理操作中,我们很可能必须透过多道SQL SELECT命令的查询、统计与运算查理才能求得所需的结果,而在其过程中,您很可能希望将某一个查询结果的Cursors 作为另外一个SQL SELECT命令的查询来源,然而在预设状态下,这是不被允许的。以下面的程序代码而言,当执行第二道SQL SELECT命令时,便会出现错误:

SELECT * FROM employee INTO CURSOR Media
SELECT * FROM Media

如果您希望将某一个查询的Cursors作为另外一个SQL SELECT 命令的查询来源,必须与希望作为查询来源之INTO CURSOR参数中加入关键字NOFILTER,以前面的简例而言,若能改写如下便是正确的:

SELECT * FROM employee INTO CURSOR Media NOFILTER
SELECT * FROM Media

然而不讳言的,由于加入关键字NOFILTER后一定会在磁盘上建立暂存文件,因此会稍稍影响查询的速度。当此Cursors被关闭时,其暂存文件会自动从磁盘上删除。

TO FILE FILENAME [ADDITIVE]

利用TO FILE FILENAME参数,您可以将查询结果储存至FILENAME参数所指定名称的ASCII文本文件中,此文本见的预设后缀名为.TXT。如果您希望目前的查询结果增添至文本文件FILENAME原先以存在内容之尾端而不覆盖掉其原有之数据,请再加入关键字ADDITIVE。例如:

SELECT * FROM employee TO FILE test ADDITIVE

如果您希望将查询结果输出于一文本文件的同时,不要将此查询结果显示于Visual FoxPro的桌面上,请再加入克选择性的关键字NOCONSOLE。例如:

SELECT * FROM employee TO FILE test ADDITIVE NOCONSOLE

TO PRINT [PROMPT]

TO PRINT 参数会将SELECT命令的查询结果输出于打印机。例如:

SELECT * FROM employee TO PRINTER

如果您于TO PRINTER参数后方在加入关键字PROMPT,则在开始打印前会先显示“打印”对话框,以便让您选择用来打印的打印机以及调整打印机的机关设定,不过此对话框种的设定选项将因您所安装至打印机的不同而有所不同。

如果您希望将查询结果输出于打印的同时,不要将此查询结果显示于Visual FoxPro的桌面上,清在加入可选择性的关键字NOCONSOLE。例如:

SELECT * FROM employee TO PRINTER PROMPT NOCONSOLE

TO SCREEN

如果您希望将查询结果输出于Visual FoxPro的桌面上,请加入TO SCREEN参数。当由SELECT 命令所产生至查询结果的行数过多而无法一次于一页屏幕画面显示完毕时,Visual FoxPro的会在每显示一页后即暂停,并要求您按任一键继续显示。如果您不需要此中每显示一页即暂停的处理,而希望一次显示完毕,请加入关键字NOWAIT。例如:

SELECT * FROM employee TO SCREEN NOWAIT

注意:

事实上关键字不仅仅只是与TO SCREEN参数合用。正如您所知道的,如果病危制定查询结果的输出目的地,则预设会输出于BROWSE视窗中,此时程序自然也就会停止继续往下执行知道您跳离BROWSE视窗为止。如果您希望在将查询结果输出至BROWSE视窗后,程序无须等待您跳离BROWSE视窗而继续往下执行的话,请加入关键字NOWAIT。

与INTO参数合用,关键字NOWAIT会被忽略。

如果您希望将查询结果输出与屏幕画面、文本文件或打印机时,能够取出各列的标题,则请加入关键字PLAIN。

阅读(5716) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册