九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
sql學(xué)習(xí)資料

跟我學(xué)SQL()數(shù)據(jù)查詢

 

且不說(shuō)你是否正在從事編程方面的工作或者不打算學(xué)習(xí)SQL,可事實(shí)上幾乎每一位開(kāi)發(fā)者最終都會(huì)遭遇它。你多半還用不著負(fù)責(zé)創(chuàng)建和維持某個(gè)數(shù)據(jù)庫(kù),但你怎么著也該知道以下的一些有關(guān)的SQL知識(shí)。
   
我為那些感興趣的開(kāi)發(fā)者或者能從數(shù)據(jù)庫(kù)操作中得益的讀者撰寫(xiě)了這篇關(guān)于基本SQL語(yǔ)法的概述性文章。本文主要討論基本的數(shù)據(jù)操作查詢,后續(xù)的文章還會(huì)繼續(xù)討論如何修改數(shù)據(jù)庫(kù)自身以及更高級(jí)的查詢概念。

SQL數(shù)據(jù)庫(kù)是怎么回事? 
SQL
(結(jié)構(gòu)化查詢語(yǔ)言)就是負(fù)責(zé)與ANSI維護(hù)的數(shù)據(jù)庫(kù)交互的標(biāo)準(zhǔn)。最新的版本是SQL-99,還有一個(gè)新標(biāo)準(zhǔn)SQL-200n尚處于制定過(guò)程中。大多數(shù)的數(shù)據(jù)庫(kù)都至少遵守ANSI-92標(biāo)準(zhǔn)的部分子集。不過(guò),目前對(duì)最新標(biāo)準(zhǔn)的有效性還存在一些爭(zhēng)論。專有數(shù)據(jù)庫(kù)制造商根據(jù)這些標(biāo)準(zhǔn)開(kāi)發(fā)自己的產(chǎn)品,同時(shí)制定出自己特有的數(shù)據(jù)庫(kù)存儲(chǔ)操作新概念。幾乎各種不同的數(shù)據(jù)庫(kù)都包含了自己特有的語(yǔ)法集合,只是通常很類似ANSI標(biāo)準(zhǔn)。在大多數(shù)情況下,盡管有一些數(shù)據(jù)庫(kù)實(shí)例基于特定的擴(kuò)展語(yǔ)法會(huì)因數(shù)據(jù)庫(kù)的不同而產(chǎn)生不同的結(jié)果,但總的說(shuō)來(lái),這些新加的語(yǔ)法不過(guò)是對(duì)原有標(biāo)準(zhǔn)的擴(kuò)充。如果數(shù)據(jù)庫(kù)操作并沒(méi)有得到你希望的結(jié)果,那么你不妨事先讀一讀數(shù)據(jù)庫(kù)制造商提供的產(chǎn)品說(shuō)明。

假如到目前為止你頭回遭遇SQL語(yǔ)言,那么你怎么也得先理解一些基本的SQL概念。我盡量把這些基本知識(shí)闡述得簡(jiǎn)明扼要,如果你對(duì)那些數(shù)據(jù)庫(kù)術(shù)語(yǔ)還能忍受,你盡可跳到下一節(jié),此外你還可以把自己的問(wèn)題提交給以下的討論區(qū)。

籠統(tǒng)地說(shuō),“SQL數(shù)據(jù)庫(kù)其實(shí)就是關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(RDMS)通俗的叫法。對(duì)某些系統(tǒng)來(lái)說(shuō),數(shù)據(jù)庫(kù)也指一組數(shù)據(jù)表、數(shù)據(jù)以及相互區(qū)分但結(jié)構(gòu)類似的配置信息。在這種情況下,每一SQL數(shù)據(jù)庫(kù)的安裝都可能由若干數(shù)據(jù)庫(kù)組成。在有些系統(tǒng)上,這種數(shù)據(jù)庫(kù)則指的是表空間。

數(shù)據(jù)表是一種包含多行數(shù)據(jù)的數(shù)據(jù)庫(kù)構(gòu)造,這種數(shù)據(jù)庫(kù)構(gòu)造由命名的列組成。通常數(shù)據(jù)表構(gòu)造為包含關(guān)系信息,同一數(shù)據(jù)庫(kù)或表空間以內(nèi)可以創(chuàng)建若干數(shù)據(jù)表。

表內(nèi)的列保存某一種類型的數(shù)據(jù)而且應(yīng)根據(jù)其保存數(shù)據(jù)的內(nèi)容得以命名。例如,被稱為“LastName”的列就應(yīng)該在每一行包含姓氏條目。正是這一前提的存在才能讓關(guān)系數(shù)據(jù)庫(kù)查詢返回一致的結(jié)果。

字段(field)指的是某一行某一列對(duì)應(yīng)的數(shù)據(jù)(或保存數(shù)據(jù)的地方)。另外,數(shù)據(jù)集合(data set)則指的是多行多列的數(shù)據(jù),而且數(shù)據(jù)集合通常說(shuō)明你的數(shù)據(jù)庫(kù)或數(shù)據(jù)表內(nèi)的全部數(shù)據(jù)。結(jié)果集合(result set)就是從數(shù)據(jù)庫(kù)查詢返回的數(shù)據(jù);它能夠描述從單一字段到數(shù)據(jù)庫(kù)內(nèi)全部數(shù)據(jù)這一范圍內(nèi)的全部信息。

數(shù)據(jù)庫(kù)查詢就是發(fā)送給數(shù)據(jù)庫(kù)的SQL指令,這些指令向數(shù)據(jù)庫(kù)請(qǐng)求某種施加在數(shù)據(jù)集合或數(shù)據(jù)庫(kù)上的功能。

現(xiàn)在我們就來(lái)看看基本的數(shù)據(jù)庫(kù)查詢,這些查詢主要涉及到對(duì)數(shù)據(jù)庫(kù)內(nèi)數(shù)據(jù)的操作。在本文中,所有的例子都采用了標(biāo)準(zhǔn)SQL語(yǔ)言,而且這些基本功能可以轉(zhuǎn)換為應(yīng)用在幾乎各種環(huán)境下。

數(shù)據(jù)查詢類型

SQL語(yǔ)言中的數(shù)據(jù)查詢分為4種基本類型:

SELECT:這條語(yǔ)句要求數(shù)據(jù)庫(kù)返回指定結(jié)果的數(shù)據(jù)集合;你可以用這一語(yǔ)句檢索數(shù)據(jù)庫(kù)中保存的信息。
INSERT
:這條語(yǔ)句用來(lái)給數(shù)據(jù)表增加新一行數(shù)據(jù)。
DELETE
:該語(yǔ)句從你的數(shù)據(jù)庫(kù)中刪除若干行數(shù)據(jù)。
UPDATE
:該語(yǔ)句修改數(shù)據(jù)庫(kù)內(nèi)的現(xiàn)有數(shù)據(jù)。
以上的這些語(yǔ)句都有各種各樣的限定詞和函數(shù)供你用來(lái)定義有關(guān)的數(shù)據(jù)集合,同時(shí)控制查詢返回的結(jié)果集合。SELECT語(yǔ)句的選項(xiàng)最多。有許多種組合SELECT的查詢選項(xiàng),例如JOINUNION等。不過(guò)就我們目前來(lái)說(shuō),本文主要還是關(guān)注基本用途。

SELECT語(yǔ)句檢索保存的信息
為了獲得數(shù)據(jù)庫(kù)中保存的信息就必須采用SELECT語(yǔ)句。其基本功能限制在針對(duì)單一數(shù)據(jù)表操作,當(dāng)然,其他范圍的構(gòu)造也是有的。為了返回特定列所對(duì)應(yīng)的所有數(shù)據(jù)行,你可以使用以下語(yǔ)句:

SELECT column1, column2 FROM table_name;

另外,使用通配符“*”可以從表中選出所有的列:

SELECT * FROM table_name;

你要愿意自己編碼分析以上返回的結(jié)果當(dāng)然也沒(méi)問(wèn)題,不過(guò)你完全可以采用方便的WHERE子句限制返回的結(jié)果集合,該子句可以讓你為選擇數(shù)據(jù)定義某些條件。以下查詢就會(huì)返回“column1”數(shù)值等于3的所以數(shù)據(jù)行:
SELECT * FROM table_name WHERE column1 = 3;

除了“=”(等于)條件之外你還可以用到下列條件運(yùn)算符:


=
等于 
<>
不等于 
>
大于 
<
小于 
>=
大于或等于 
<=
小于或等于 

SQL 條件語(yǔ)句

另外,你還可以聯(lián)合WHERE語(yǔ)句使用BETWEEN、LIKE等比較運(yùn)算符以及ANDOR這類邏輯運(yùn)算符。注意,OR語(yǔ)句是包含性的的。以下有一個(gè)例子組合了以上這些概念:

SELECT * FROM table_name WHERE ((Age < 18) AND (LastName BETWEEN ‘Anderson’ AND ‘Miller’)) OR Company LIKE ‘%School%’;

用自然語(yǔ)言來(lái)說(shuō),這條選擇語(yǔ)句的含義是這樣的:從數(shù)據(jù)表中選出年齡小于18歲而且姓氏在“Anderson”“MIller”之間的或者其公司名稱類中有“School”字樣的數(shù)據(jù)行。

INSERT語(yǔ)句加入新數(shù)據(jù)
使用INSERT語(yǔ)句可以創(chuàng)建新的數(shù)據(jù)行。如果你希望在某一行的某個(gè)字段中賦值則要用到UPDATE語(yǔ)句。

插入語(yǔ)句的語(yǔ)法如下:
INSERT INTO table_name (column1, column2, column3)
VALUES (‘data1’, ‘data2’, ‘data3’);

如果你想按照表內(nèi)現(xiàn)有列的同一順序插入所有的值,那么你不必指定列名,當(dāng)然,從可讀性考慮最好不要這樣做。另外,如果你列出列名則不必要按照它們?cè)跀?shù)據(jù)庫(kù)中出現(xiàn)的順序包括它們,只要你列出的值與它們一一對(duì)應(yīng)即可。有些列你并沒(méi)有為其輸入新的信息所以你自然沒(méi)有必要列出它們來(lái)。

一旦數(shù)據(jù)庫(kù)中有了數(shù)據(jù)要修改起來(lái)也與此很相似。

UPDATE語(yǔ)句和WHERE子句
UPDATE
用來(lái)修改現(xiàn)有的值或行里的空字段,因此它必須在匹配現(xiàn)有的數(shù)據(jù)集合同時(shí)提供可接受的值。除非你真地想要修改所有數(shù)據(jù)行上的值,否則你必須使用WHERE子句。
UPDATE table_name SET column1 = ‘data1’, column2 = ‘data2’
      WHERE column3 = ‘data3’;

你可以采用WHERE子句隨意匹配任何一列,正在修改的一列都可以。這樣會(huì)有助于你把某一特定的值修改為另一個(gè)值:

UPDATE table_name SET FirstName = ‘Shelley’
WHERE FirstName = ‘Shelly’ AND LastName = ‘Doll’;
小心DELETE語(yǔ)句
DELETE
語(yǔ)句會(huì)從數(shù)據(jù)庫(kù)的數(shù)據(jù)表中刪除整行。如果你僅僅想刪除單一的字段則應(yīng)該使用UPDATE語(yǔ)句把它修改為代表應(yīng)用程序中的NULL的其他空值。一定要小心使用帶WHERE子句的DELETE語(yǔ)句,否則你可能會(huì)遭遇清空全部數(shù)據(jù)表的風(fēng)險(xiǎn)。
DELETE FROM table_name WHERE column1 = ‘data1’;

一旦你數(shù)據(jù)庫(kù)中刪除某一行數(shù)據(jù)就不可再后悔了,因此一般來(lái)說(shuō),最好在數(shù)據(jù)表中包括一名為“IsActive”的列或類似的指示信息,這樣你就可以把該列數(shù)據(jù)設(shè)置為零表示數(shù)據(jù)禁用。只有在你確信不再需要受到影響的信息之后你才可以用DELETE語(yǔ)句。

小結(jié)
SQL
就是數(shù)據(jù)庫(kù)的語(yǔ)言,我們已經(jīng)了解了數(shù)據(jù)查詢中所采用的最基本命令語(yǔ)句。但還有很多基本概念尚未涉及,例如SUNCOUNT函數(shù)等,但以上列出的這些命令應(yīng)該足夠你開(kāi)始著手?jǐn)?shù)據(jù)庫(kù)操作了。

跟我學(xué)SQL() SELECT語(yǔ)句選項(xiàng)

跟我學(xué)SQL分為三部分,其中涵蓋了有關(guān)SQL標(biāo)準(zhǔn)的基本知識(shí)。在上一篇文章里我們討論了一些數(shù)據(jù)庫(kù)術(shù)語(yǔ)和4種最基本的數(shù)據(jù)查詢類型。此外,我們還解釋了WHERE子句和條件語(yǔ)句的用法,同時(shí)我們提供了各類查詢的具體示例。 
在這篇文章里,我們將就其他一些SQL函數(shù)和子句進(jìn)行闡述,供你用于基本的SELECT數(shù)據(jù)查詢中。

SELECT選項(xiàng)精制結(jié)果
正如我們從上一篇文章中所讀到的那樣,SELECT語(yǔ)句具有種類繁多的各類選項(xiàng),這些選項(xiàng)可以用來(lái)控制數(shù)據(jù)返回的方式。這些選項(xiàng)以子句、關(guān)鍵詞和函數(shù)的形式存在。

子句是一種修改結(jié)果的語(yǔ)句。子句不是必要的語(yǔ)句但它對(duì)數(shù)據(jù)的內(nèi)容及其顯示進(jìn)行了提煉。WHERE子句就是這樣的子句。

關(guān)鍵詞觸發(fā)數(shù)據(jù)庫(kù)的內(nèi)在功能。這些關(guān)鍵詞在有時(shí)甚至是查詢所必需的。例如“INSERT INTO table_name (column1) VALUES (‘data1’);”語(yǔ)句中的INTOVALUE就是如此。我們將了解DISTINCT關(guān)鍵詞,它能觸發(fā)一些非常有用的可選功能。

下面總結(jié)了一些最常用的子句、關(guān)鍵詞和函數(shù)。然后我會(huì)對(duì)每一部分舉例說(shuō)明。

ORDER BY – 按照指定列排序返回結(jié)果的子句
DISTINCT –
只返回結(jié)果集合內(nèi)唯一行的關(guān)鍵詞
COUNT --
返回匹配查詢的數(shù)據(jù)行總數(shù)數(shù)值的函數(shù)
AVG –
該函數(shù)返回指定列的平均值
SUM –
該函數(shù)把指定的列中的數(shù)字加起來(lái)
MIN –
該函數(shù)返回列中最小的非NULL
MAX –
該函數(shù)返回列中的最大值
GROUP BY –
按列匯集查詢函數(shù)結(jié)果的子句
ORDER BY對(duì)查詢結(jié)果排序
ORDER BY
子句讓數(shù)據(jù)庫(kù)對(duì)查詢結(jié)果排序,這樣你就無(wú)須自己編寫(xiě)應(yīng)用程序進(jìn)行手工排序了。ORDER BY子句必須放在查詢語(yǔ)句的結(jié)尾。其基本用法如下:

SELECT * FROM Contacts ORDER BY first_name;

你可以隨意在任何選擇語(yǔ)句中使用ORDER BY 子句返回多列結(jié)果。你還可以用它連接其他子句:
SELECT first_name, last_name FROM Contacts WHERE first_name BETWEEN ‘a’ AND ‘k’ ORDER BY last_name;

你可以對(duì)多列數(shù)據(jù)排序。優(yōu)先順序按從左到右依次降低,所以查詢語(yǔ)句中各列的排列順序很重要。
SELECT * FROM Contacts ORDER BY company, last_name, first_name;

查詢結(jié)果默認(rèn)按數(shù)字或者字母的升序排序。你可以在ORDER BY 子句后面加上DESC關(guān)鍵詞改成降序排列。在下面的例子中,最高的net_amount排在最先(降序)。假如兩行或者兩行以上數(shù)據(jù)都包含了同樣的net_amount值,那么同行中last_name值在字母表中最先出現(xiàn)的排先,因?yàn)?span lang="EN-US">last_name一列還是按照升序排序的。
SELECT * FROM Sales ORDER BY net_amount DESC, last_name, first_name;

在按照定義的列名排序以后,大多數(shù)數(shù)據(jù)庫(kù)隨后將按照數(shù)據(jù)表內(nèi)的第一列排序然后順序向右再排序。具體的實(shí)現(xiàn)各有變化,因此,如果排序在應(yīng)用中比較重要那么你應(yīng)該明確地定義所要排序的列。

另外一值得注意的問(wèn)題是,采用ORDER BY子句(以及WHERE子句),你正在用來(lái)排序結(jié)果的數(shù)據(jù)列并不一定得是返回結(jié)果集合的一部分。只要所有引用的列都在數(shù)據(jù)表內(nèi)存在則下例完全有效:

SELECT company, first_name, net_amount FROM Sales ORDER BY start_date, last_name;

DISTINCT返回不重復(fù)結(jié)果 
DISTINCT
關(guān)鍵詞只返回結(jié)果集合內(nèi)不重復(fù)的數(shù)據(jù)行。例如,有時(shí)你可能需要找出Sales表內(nèi)的公司,但是你又不想看見(jiàn)每個(gè)條目。于是你可以用DISTINCT對(duì)應(yīng)每一公司名返回一行數(shù)據(jù):

SELECT DISTINCT company FROM Sales;

在使用DISTINCT時(shí),它適用于所有的請(qǐng)求列。如果你打算列出表內(nèi)的所有銷售人員和他們所代表的公司而非每一銷售記錄,那么你可以使用下列語(yǔ)句。注意,這樣操作還可能返回同一公司的若干條目等等。

SELECT DISTINCT company, last_name, first_name FROM Sales;

你還可以在對(duì)結(jié)果縮小范圍和進(jìn)行排序時(shí)結(jié)合SELECT語(yǔ)句使用DISTINCT。為了確定顯示的內(nèi)容,數(shù)據(jù)庫(kù)首先會(huì)證實(shí)精練的請(qǐng)求是否匹配數(shù)據(jù)行,然后應(yīng)用DISTINCT功能。在全部結(jié)果集合都得以確定之后即處理ORDER BY子句。如下例所示,只有net_amount大于100的數(shù)據(jù)行才被返回。由于DISTINCT保留遇見(jiàn)的第1個(gè)匹配查詢條件的數(shù)據(jù)行而丟棄其他匹配行,所以ORDER BY語(yǔ)句所引用的net_amount看起來(lái)就好象產(chǎn)生了隨機(jī)的結(jié)果。

SELECT DISTINCT company, last_name, first_name FROM Sales WHERE net_amount > 100 ORDER BY company, net_amount;
函數(shù)應(yīng)用邏輯
返回單一值的函數(shù)稱做聚集函數(shù)(aggregate function)。通過(guò)應(yīng)用程序訪問(wèn)下列聚集函數(shù)的結(jié)果時(shí),包含結(jié)果的字段名就是你所使用的實(shí)際函數(shù)。例如,在分析你的數(shù)據(jù)庫(kù)結(jié)果時(shí),結(jié)果數(shù)組的鍵值可能如下所示:

$keyname = “COUNT(*)”;
$resultkey = “AVG(net_amount)”;

COUNT
COUNT
函數(shù)計(jì)算出結(jié)果集合中的數(shù)據(jù)行數(shù)。和其他函數(shù)一樣它接受一個(gè)參數(shù)。以下的基本示例能告訴你數(shù)據(jù)表內(nèi)的行數(shù):SELECT COUNT(*) FROM Sales;

你也可以用它來(lái)計(jì)算任何結(jié)果集合中的行數(shù)。

SELECT COUNT(*) FROM Sales WHERE net_amount > 100;

如果你想看看某特定列有多少行包含非空值,那你不妨對(duì)該列使用COUNT函數(shù)。注意,除非數(shù)據(jù)庫(kù)設(shè)置為字段為空時(shí)缺省填充NULL否則將返回表內(nèi)數(shù)據(jù)行的總數(shù)。另外,列出的列在超出一個(gè)的情況下會(huì)引起錯(cuò)誤。

SELECT COUNT(company) FROM Sales; 
COUNT
還可以用來(lái)計(jì)算DISTINCT結(jié)果集合中的行數(shù)。
SELECT COUNT(DISTINCT company, last_name) FROM Sales;

COUNT語(yǔ)句通常用在程序中確定FOR循環(huán)的循環(huán)次數(shù)。
AVG
AVG
返回某列所有字段的平均值,該列必須是數(shù)字?jǐn)?shù)據(jù)類型。該函數(shù)用列的名字作為其參數(shù),如果列字段數(shù)據(jù)類型是非數(shù)字類型的則函數(shù)返回0”。SELECT AVG(net_amount) FROM Sales;

你可以結(jié)合子句限制該函數(shù)的應(yīng)用范圍。

SELECT AVG(net_amount) FROM Sales WHERE company LIKE ‘%ABCD Co%’;

就象所有聚集函數(shù)一樣,ORDER BY語(yǔ)句將被忽略。

SUM

SUM的工作方式和AVG差不多,只不過(guò)該函數(shù)返回結(jié)果集合中所有字段值的和。
SELECT SUM(net_amount) FROM Sales WHERE net_amount > 100;

AVG、SUMMINMAX函數(shù)在沒(méi)有指定列的情況下都會(huì)返回錯(cuò)誤,所以你不能使用“*”通配符。

MIN
MIN
返回指定列中最小的非空值。如果指定列是數(shù)字?jǐn)?shù)據(jù)類型則結(jié)果將是最小的數(shù)字。如果它是一種字符串?dāng)?shù)據(jù)類型則函數(shù)將返回按字母表順序出現(xiàn)的第1個(gè)值。SELECT MIN(net_amount) FROM Sales WHERE last_name = “Smith”;
SELECT MIN(last_name) FROM Sales; 

MAX

MAX的工作方式和MIN函數(shù)一樣,只不過(guò)該函數(shù)返回最大的非空值。該函數(shù)也可以用于字符串或者數(shù)字列
SELECT MAX(net_amount) FROM Sales;
SELECT MAX(company) FROM Sales WHERE net_amount > 100;

MAX函數(shù)有時(shí)還用在包含自動(dòng)遞增鍵字段的列上確定下一條目的鍵ID。除非你正在運(yùn)行一個(gè)非公開(kāi)的數(shù)據(jù)庫(kù),否則在使用這一信息插入下一條目時(shí)務(wù)必謹(jǐn)慎,以防其他用戶先你執(zhí)行數(shù)據(jù)操作。
GROUP BY
令函數(shù)更有用 
雖然以上提到的所有這些函數(shù)都能提供相當(dāng)有用的信息,但是,如果有GROUP BY子句幫忙的話更能讓你在列的字段子集中應(yīng)用這些函數(shù)。不要對(duì)你的Sales表中每一家公司一次又一次地執(zhí)行MAX函數(shù)查詢——你完全可以帶GROUP BY子句獲得同樣的結(jié)果:

SELECT company, MAX(net_amount) FROM Sales GROUP BY company;

這樣做可以獲得每家公司net_amount的的最大值。在選擇多列名的時(shí)候也可以采用該語(yǔ)句,你還可以用多列來(lái)對(duì)函數(shù)結(jié)果分組。

下面的例子演示了以上各種方式。首先,包括GROUP BY子句可以令你指定要顯示的其他列。然而,你得知道這個(gè)例子將返回在組中遇到的第1個(gè)last_name值;Sum( net_amount )將顯示全部公司的結(jié)果而不僅僅針對(duì)匹配姓氏的數(shù)據(jù)行。這是因?yàn)?,我們只使用?span lang="EN-US">Company字段來(lái)定義我們的組。

SELECT company, last_name, SUM(net_amount) FROM Sales GROUP BY company;

在上面的例子中,last_name列實(shí)際上并沒(méi)有提供什么有用的信息,但這樣做是為了在下一個(gè)例子中要用到的功能做準(zhǔn)備。你可以創(chuàng)建多列定義的組。這樣就可以在結(jié)果集合中產(chǎn)生針對(duì)特定行的函數(shù)結(jié)果,而結(jié)果集合則是由所有指定的GROUP BY列聯(lián)合起來(lái)創(chuàng)建的:

SELECT company, AVG(net_amount), last_name FROM Sales GROUP BY company, last_name; 

上面的例子給每家公司中每一姓氏給出了平均的net_amount。你列出GROUP BY列的順序控制著結(jié)果的排序,但是實(shí)際的函數(shù)值結(jié)果是一樣的。

下面的例子表明如何組織結(jié)果而不顯示分組的列。在有些場(chǎng)合這樣做是很有用的,例如,如果要顯示個(gè)人的銷售量但卻不顯示姓名就能用上下面的例子了:

SELECT company, COUNT(sale_id) FROM Sales GROUP BY company, last_name;

限制使用GROUP BY的查詢
如你在以上示例中所看到的那樣,你可以結(jié)合WHERE字句利用以上的概念限制查詢的范圍。WHERE子句會(huì)首先被計(jì)算,然后執(zhí)行函數(shù)。在使用組的時(shí)候就是這樣的。

SELECT company, AVG(net_amount), FROM Sales WHERE net_amount > 100 GROUP BY company;

上面的例子只對(duì)那些滿足WHERE限制條件的數(shù)據(jù)行適用AVG函數(shù)。注意,WHERE子句必須放在GROUP BY子句之前。你還可以用HAVING語(yǔ)句對(duì)分組計(jì)算之后限制返回的結(jié)果集合。

SELECT company, AVG(net_amount), FROM Sales WHERE last_name BETWEEN ‘a’ AND ‘m’ GROUP BY company HAVING AVG(net_amount) > 500; 

上面的語(yǔ)句計(jì)算每家公司net_amount的平均值,而且只計(jì)算那些姓氏滿足限制條件的銷售人員的銷售量,同時(shí)只顯示大于500的結(jié)果。

跟我學(xué)SQL()使用SQL子選擇來(lái)合并查詢

你是否曾經(jīng)為了得到所需要的信息而反復(fù)查詢?子選擇,也被稱為子查詢,也許正是你在尋找的。SQL的這項(xiàng)功能使你可以在一組結(jié)果中查詢,創(chuàng)造性地給結(jié)果組加以限定,或是在向數(shù)據(jù)庫(kù)的單一調(diào)用中將結(jié)果與一個(gè)無(wú)關(guān)系的查詢做相關(guān)。這篇文章中我將給出幾個(gè)子選擇的例子并就何時(shí)使用他們進(jìn)行討論。

在一個(gè)結(jié)果組中搜索
 
子選擇的理念很簡(jiǎn)單:一個(gè)選擇查詢安置在另一個(gè)查詢內(nèi)部,創(chuàng)建一個(gè)在單一聲明搜索中不可用的資源。子選擇允許查詢的合并,結(jié)果組比較的責(zé)任落到了數(shù)據(jù)庫(kù)中而不是應(yīng)用軟件代碼中。

使用這個(gè)功能的一個(gè)途徑是對(duì)兩個(gè)表格中的可比數(shù)據(jù)專欄中的值進(jìn)行定位。例如,我的一個(gè)數(shù)據(jù)庫(kù)有兩個(gè)表格,AlbumLyric。我可以很容易地通過(guò)下面的子查詢聲明來(lái)找到每一個(gè)Metallica的歌曲中包含“justice”的歌名:

SELECT song_name FROM Album
WHERE band_name = ‘Metallica’
AND song_name IN
(SELECT song_name FROM Lyric
WHERE song_lyric LIKE ‘%justice%’);

這個(gè)例子是很簡(jiǎn)單的,我從Album表格中選擇了所有Metallica的歌曲,接著,我在lyric表格中選擇所有包含“justice”的歌曲,最后,我使用IN關(guān)鍵字來(lái)從Lyric表格結(jié)果組中顯示的Album表格中返回歌曲名稱。

我使用Lyric表格結(jié)果組來(lái)給Album表格中的結(jié)果做限定。WHERE子句中的子選擇部分是完全自包含的,因此我不需要使用例如Album.song_nameLyric.song_name等完整的專欄名稱。我沒(méi)有從最終結(jié)果組的Lyric表格中返回任何值,如果我需要歌曲的Lyric,我會(huì)使用一個(gè)JOIN聲明。

使用NOT IN排除結(jié)果
你可以使用NOT IN關(guān)鍵字來(lái)獲得明確地不被包含在另一個(gè)結(jié)果組中的結(jié)果。例如,我想要通過(guò)下面的代碼來(lái)返回Metallica“And Justice for All”專輯中不包含單詞“justice”的歌曲:

SELECT song_name FROM Album
WHERE album_name = ‘And Justice for All’
AND band_name = ‘Metallica’
AND song_name NOT IN
(SELECT song_name FROM Lyric
WHERE song_lyric LIKE ‘%justice%’);

在前面的SQL代碼中,我選擇了Metallica“And Justice for All,”專輯中的所有歌曲,接著是帶有歌詞中帶有“justice”所有歌曲,最后從在Lyric結(jié)果組中沒(méi)有出現(xiàn)的Album結(jié)果組返回了所有歌曲。較之于返回兩個(gè)查詢并使用代碼來(lái)比較數(shù)組,你通過(guò)一個(gè)單獨(dú)的聲明就可以得到確切的結(jié)果。

使用EXISTS來(lái)相關(guān)結(jié)果
有時(shí)你可以通過(guò)多種途徑來(lái)訪問(wèn)相同的數(shù)據(jù),而且你需要對(duì)你的結(jié)果進(jìn)行匹配(或相關(guān))來(lái)得到值的交叉區(qū)。例如,我可以通過(guò)搜索Album表格來(lái)得到Metallica的歌曲列表,可是,我也可以從我的Cover表格中得到由Damage, Inc表演的Metallica的歌曲的列表,我可以在兩個(gè)表格中直接比較查詢結(jié)果來(lái)對(duì)值作相關(guān)。

SELECT Album.song_name FROM Album
WHERE Album.band_name = ‘Metallica’
AND EXISTS
(SELECT Cover.song_name FROM Cover
WHERE Cover.band_name = ‘Damage, Inc.’
AND Cover.song_name = Album.song_name);

SQL代碼中,我使用完整的專欄名稱,這是因?yàn)槲抑苯訉?duì)兩個(gè)表格作比較,而不僅僅是將結(jié)果組作為一個(gè)被動(dòng)資源來(lái)使用。我并不從Cover表格中返回結(jié)果。一些數(shù)據(jù)庫(kù)支持NOT EXISTS關(guān)鍵字來(lái)確保你并沒(méi)有匹配。

使用合計(jì)函數(shù)來(lái)比較
 
除了使用子選擇在相關(guān)的表格中檢查數(shù)據(jù),你還可以在一個(gè)WHERE子選擇中使用合計(jì)函數(shù)來(lái)確定主結(jié)果組。例如,我想要核實(shí)每一個(gè)Metallica歌曲在Album表格中的條目。而且,我還想返回缺少歌曲的專輯的名稱。很方便地,AlbumInfo表格包含的一個(gè)專欄(album_tracks)給出了應(yīng)該有多少首歌曲方面的信息。

SELECT AlbumInfo.album_name FROM AlbumInfo
WHERE AlbumInfo.band_name = ‘Metallica’
AND album_tracks <>
(SELECT COUNT(*) FROM Album
WHERE Album.album_name = AlbumInfo.album_name);

現(xiàn)在我已經(jīng)成功地返回了所有Metallica的專輯中,應(yīng)有的曲目數(shù)量與Album表格中實(shí)際的歌曲條目數(shù)量不符的專輯名稱。

返回子選擇結(jié)果
如果我還是關(guān)心每一張專輯的曲目數(shù)量并需要得到一個(gè)比較報(bào)告怎么辦?你可以將一個(gè)子選擇的結(jié)果作為最終結(jié)果組的一部分來(lái)返回。這個(gè)功能經(jīng)常被合計(jì)函數(shù)所使用。通常地,對(duì)其他表格的訪問(wèn)可以作為你的查詢的一部分。下一個(gè)例子將返回每一張Metallica的專輯,應(yīng)該包括的曲目數(shù)量和在Album表格中包括的條目數(shù)量:

SELECT AlbumInfo.album_name, album_tracks,
(SELECT COUNT(*) FROM Album
WHERE Album.album_name = AlbumInfo.album_name)
FROM  AlbumInfo
WHERE AlbumInfo.band_name = ‘Metallica’;

另一個(gè)強(qiáng)有力的例子涉及了在AlbumInfo表格中將album_tracks值改變?yōu)樵?span lang="EN-US">Album表格中實(shí)際的條目數(shù)量:

UPDATE AlbumInfo SET album_tracks =
SELECT COUNT(*) FROM Album
WHERE AlbumInfo.album_name = Album.album_name)
WHERE AlbumInfo.band_name = ‘Metallica’;

在上兩個(gè)例子中的子選擇聲明被看作一個(gè)自包含單位來(lái)執(zhí)行。

子選擇比較關(guān)鍵字(ALL, SOME, ANY)
除了使用標(biāo)準(zhǔn)查詢功能,還有三個(gè)關(guān)鍵字可以使你將一個(gè)表達(dá)式值和一個(gè)單欄子選擇聲明結(jié)果組作比較,這些關(guān)鍵字返回TRUEFALSEBoolean值。ALL關(guān)鍵字要求子選擇中所有值都遵守比較運(yùn)算符。SOMEANY關(guān)鍵字則要求至少一對(duì)。這里是ALL關(guān)鍵字的一個(gè)簡(jiǎn)單實(shí)例。

SELECT * FROM AlbumSales
WHERE album_gross >
ALL (SELECT album_costs FROM AlbumProduction);

上面的例子將從AlbumSales表格返回在AlbumProduction表格里面付出總額大于成本而生產(chǎn)最昂貴的專輯的所有記錄。如果用ANY替代ALL,聲明將返回所有付出總額大于最低專輯成本的專輯記錄。聲明= ANYIN關(guān)鍵字意義是相同的。聲明<> ALLNOT IN關(guān)鍵字是對(duì)等的。關(guān)鍵字ANYSOME也是等同的。數(shù)據(jù)庫(kù)生產(chǎn)商中對(duì)這些關(guān)鍵字的支持情況是不同的,因此在出現(xiàn)問(wèn)題時(shí)要相信查閱生產(chǎn)商方面的資料。

誰(shuí)對(duì)標(biāo)準(zhǔn)化數(shù)據(jù)結(jié)構(gòu)有疑問(wèn)?
子選擇查詢句法是簡(jiǎn)單易懂的,而懂得何時(shí)使用它卻是一個(gè)難點(diǎn)。如果你曾經(jīng)在標(biāo)準(zhǔn)化數(shù)據(jù)結(jié)構(gòu)方面出現(xiàn)問(wèn)題,子選擇聲明將幫助你獲得更深入的了解。

跟我學(xué)SQL()查詢多個(gè)表格

在對(duì)跨多個(gè)表格的數(shù)據(jù)進(jìn)行組合時(shí),有時(shí)很難搞清楚要使用哪一個(gè)SQL句法。我將在這里對(duì)將多個(gè)表格中的查詢合并至單一聲明中的常用方式進(jìn)行闡述。

在這篇文章中的樣本查詢符合SQL92 ISO標(biāo)準(zhǔn)。不是所有的數(shù)據(jù)庫(kù)生產(chǎn)商都遵循這項(xiàng)標(biāo)準(zhǔn),而且很多廠商采取的提升措施會(huì)帶來(lái)一些意料不到的后果。如果你不確定你的數(shù)據(jù)庫(kù)是不是支持這些標(biāo)準(zhǔn),你可以參看生產(chǎn)廠商的有關(guān)資料。

SELECT

一個(gè)簡(jiǎn)單的SELECT聲明就是查詢多個(gè)表格的最基本的方式。你可以在FROM子句中調(diào)用多個(gè)表格來(lái)組合來(lái)自多個(gè)表格的結(jié)果。這里是一個(gè)它如何工作的實(shí)例:

SELECT table1.column1, table2.column2 FROM table1, table2 WHERE table1.column1 = table2.column1;

這個(gè)實(shí)例中,我使用點(diǎn)號(hào)(table1.column1)來(lái)指定專欄來(lái)自哪一個(gè)表格。如果所涉及的專欄只在一個(gè)參考的表格中出現(xiàn),你就不需要加入完整的名稱,但是加入完整名稱會(huì)對(duì)可讀性起到幫助。

FROM子句中表格之間由逗號(hào)來(lái)分隔,你可以加入所需的任意多的表格,盡管一些數(shù)據(jù)庫(kù)有一個(gè)在引入正式的JOIN聲明之前他們可以有效地處理的內(nèi)容這方面的限制,這個(gè)將在下面談到。

這個(gè)句法是一個(gè)簡(jiǎn)單的INNER JOIN。一些數(shù)據(jù)庫(kù)將它看成與一個(gè)外部的JOIN是等同的。WHERE子句告知數(shù)據(jù)庫(kù)哪一個(gè)區(qū)域要做關(guān)聯(lián),而且它返回結(jié)果時(shí),就像列出的表格在給定的條件下組合成一個(gè)單獨(dú)的表格一樣。值得注意的是,你的比較條件并不需要與你作為結(jié)果組返回的專欄相同。在上面的例子中,table1.column1table2.column1用來(lái)組合表格,但是返回的卻是table2.column2

你可以在WHERE子句中使用AND關(guān)鍵字來(lái)將這個(gè)功能擴(kuò)展至多于兩個(gè)的表格。你還可以使用這樣的表格組合來(lái)限制你的結(jié)果而不用實(shí)際地從每個(gè)表格返回專欄。在下面的例子中,table3table1匹配,但是我沒(méi)有從table3返回任何東西來(lái)顯示。我只是確保來(lái)自table1的有關(guān)專欄存在于table3之中。注意此例中table3需要在FROM子句中被引用。

SELECT table1.column1, table2.column2 FROM table1, table2, table3 WHERE table1.column1 = table2.column1 AND table1.column1 = table3.column1;

然而,要注意的是,這個(gè)查詢多個(gè)表格的方式是一個(gè)暗指的JOIN。你的數(shù)據(jù)庫(kù)可能對(duì)事物進(jìn)行不同的處理,這取決于它所使用的優(yōu)化引擎。而且,忽略對(duì)與WHERE子句的相關(guān)特性的定義將會(huì)給你帶來(lái)不愿看到的結(jié)果,例如從余下的查詢中返回與每一個(gè)可能的結(jié)果相關(guān)的專欄的rogue域,就像在CROSS JOIN之中一樣。

如果你習(xí)慣于你的數(shù)據(jù)庫(kù)處理這種類型的聲明的方式,且你只對(duì)兩個(gè)或是少數(shù)幾個(gè)表格進(jìn)行組合,一個(gè)簡(jiǎn)單的SELECT聲明就可以達(dá)到目的。
JOIN
 
JOIN
的工作方式與SELECT聲明是相同的,它從不同的表格中返回一個(gè)帶有專欄的結(jié)果組。在暗含的JOIN之上使用外部JOIN的優(yōu)勢(shì)是對(duì)你的結(jié)果組的更好的控制,而且還可能在涉及很多個(gè)表格的情況下提升性能表現(xiàn)。

JOIN的類型有幾種:LEFT,RIGHT,FULL OUTER,INNERCROSS。你所使用的類型是由你想要看到的結(jié)果所決定的。例如,使用LEFT OUTER JOIN將會(huì)從列出的第一個(gè)表格中返回所有有關(guān)的行,而同時(shí)如果沒(méi)有信息與第一個(gè)表格相關(guān)的話將潛在地從所列出的第二個(gè)表格中加入行。

在這里INNER JOIN和暗含的JOIN是不同的,INNER JOIN將只返回那些在兩個(gè)表格中都有數(shù)據(jù)的行。

對(duì)第一個(gè)SELECT查詢使用如下JOIN聲明:

SELECT table1.column1, table2.column2 FROM table1 INNER JOIN table2
ON table1.column1 = table2.column1;

 

子查詢
子查詢,或叫子選擇聲明,是在一個(gè)查詢中將結(jié)果組作為資源使用的一個(gè)途徑。他經(jīng)常被用來(lái)對(duì)結(jié)果進(jìn)行限制或定義,而不是運(yùn)行多個(gè)查詢或操縱應(yīng)用軟件之中的數(shù)據(jù)。有了子查詢,你可以參考表格來(lái)決定數(shù)據(jù)的內(nèi)含,或是在一些情況下,返回一個(gè)專欄,而這個(gè)專欄是一個(gè)子選擇的結(jié)果。

下面的例子中使用了兩個(gè)表格。一個(gè)表格中包含了我想要返回的數(shù)據(jù),而另一個(gè)表格則給出一個(gè)比較點(diǎn)來(lái)確定什么數(shù)據(jù)是我確實(shí)感興趣的。

SELECT column1 FROM table1 WHERE EXISTS ( SELECT column1 FROM table2 WHERE table1.column1 = table2.column1 );

子查詢很重要的一個(gè)方面就是性能表現(xiàn)。便利性是有代價(jià)的,它取決于你所使用的表格和聲明的大小,數(shù)量和復(fù)雜性,還有你可能會(huì)允許你的應(yīng)用軟件做處理工作。每一個(gè)查詢?cè)诒恢鞑樵冏鳛橘Y源使用之前,都將被完整地單獨(dú)處理。如果可能的話,創(chuàng)造性地使用JOIN聲明可以以較少的滯后時(shí)間提供出相同的信息。

JOIN聲明和子查詢
對(duì)于JOINS的更詳細(xì)的闡述和有關(guān)的理念,請(qǐng)參閱 掌握連接的一些概念。關(guān)于子查詢的更多內(nèi)容,請(qǐng)參閱使用SQL子選擇來(lái)合并查詢。

跟我學(xué)SQL()創(chuàng)建和修改表格

再次歡迎您來(lái)到SQL(結(jié)構(gòu)化查詢語(yǔ)言)基礎(chǔ)系列教程。本文將介紹數(shù)據(jù)庫(kù)定義語(yǔ)言(DDL)用于創(chuàng)建數(shù)據(jù)庫(kù)和表格以及修改表格結(jié)果的指令。

當(dāng)你使用這些指令時(shí)一定要小心——它很容易刪去你的數(shù)據(jù)庫(kù)中的主要結(jié)構(gòu)令您丟失數(shù)據(jù)。所以,在您開(kāi)始修改數(shù)據(jù)庫(kù)之前,您需要知道數(shù)據(jù)庫(kù)是什么。

數(shù)據(jù)庫(kù)之間的差異
本文中的樣品查詢系統(tǒng)遵循SQL92 ISO標(biāo)準(zhǔn)。并不是所有的數(shù)據(jù)庫(kù)都遵循該標(biāo)準(zhǔn),有些數(shù)據(jù)庫(kù)做了改進(jìn),這會(huì)產(chǎn)生不可預(yù)料的結(jié)果。如果你不能確定你的數(shù)據(jù)庫(kù)是否支持該標(biāo)準(zhǔn),請(qǐng)參考相應(yīng)的文檔。

創(chuàng)建數(shù)據(jù)庫(kù)
為了創(chuàng)建表格,你首先需要需要?jiǎng)?chuàng)建一個(gè)可以容納表格的數(shù)據(jù)庫(kù)。SQL用于創(chuàng)建數(shù)據(jù)庫(kù)的基本語(yǔ)句是:
CREATE DATABASE dbname;

你的數(shù)據(jù)庫(kù)用戶必須有建立數(shù)據(jù)庫(kù)的適當(dāng)權(quán)限。如果與你有關(guān)的用戶不能發(fā)出用于創(chuàng)建新數(shù)據(jù)庫(kù)的命令,要求數(shù)據(jù)庫(kù)管理員為你建立數(shù)據(jù)庫(kù),你也作為管理員登錄然后建立數(shù)據(jù)庫(kù)并設(shè)置權(quán)限。

舉個(gè)例子,用CREATE指令為一個(gè)應(yīng)用程序建立一個(gè)數(shù)據(jù)庫(kù)用于顯示一個(gè)目錄:
CREATE DATABASE Catalog;

這給你一個(gè)用于在查詢時(shí)與其它表格區(qū)分的表格名字。下一步是創(chuàng)建用于輸入它的表格。

創(chuàng)建表格
如你所知,表格是有若干個(gè)欄目所組成。當(dāng)創(chuàng)建表格時(shí),你可以定義欄目并分配字段屬性。表格建立后,可以用ALTER表格指令來(lái)修改它,我們稍后將提到這一點(diǎn)。

你可以用下面這條指令來(lái)創(chuàng)建數(shù)據(jù)庫(kù),命令行的參數(shù)為表格名字、欄目名字,還有每一欄的數(shù)據(jù)類型。
CREATE TABLE table_name
(column1 data_type, column2 data_type, column3 data_type);

不同的數(shù)據(jù)庫(kù)提供商的標(biāo)準(zhǔn)差別很大。你的幫助文檔中應(yīng)該有一段詳細(xì)說(shuō)明如何使用每一種數(shù)據(jù)、接受何種參數(shù)。為了通用,我在表A中列出了一些常用的數(shù)據(jù)類型。

A
 
數(shù)據(jù)類型
 
用法
 
詳細(xì)說(shuō)明
 Char
 Char(8)
 
它包含了一個(gè)固定長(zhǎng)度的字符串,其值常常是字符串長(zhǎng)度。
 Varchar
 Varchar(128)
 
它包含了一個(gè)長(zhǎng)度不大于指定值的長(zhǎng)度可變的字符串。
 Int
 Int(32)
 
這是一個(gè)不大于指定值得整數(shù),也做NumberInteger。
Decimal
 Decimal(12,2)
 
這是一個(gè)總位數(shù)和小數(shù)點(diǎn)后位數(shù)不大于指定值得小數(shù),也被稱為NumericNumber。
 Binary
 Binary
 
用于存儲(chǔ)二進(jìn)制對(duì)象,在數(shù)據(jù)庫(kù)中它一般不可分解和顯示,也稱為RawBlob。
Boolean
 Boolean
 
用來(lái)只是真或假,也成為BitByte
 
通用數(shù)據(jù)類型

在本例中,我們建立了一個(gè)存放庫(kù)存商品信息的表格。所用到的欄目和數(shù)據(jù)類型如表B所示:

B
欄目名稱:
 prod_id
 prod_color
 prod_descr
 prod_size
 
數(shù)據(jù)類型:
 Int(16)
 Varchar(20)
 Varchar(255)
 Decimal(8,2)
 
在本例中,我使用了三種基本數(shù)據(jù)類型;然而,在實(shí)際使用時(shí),根據(jù)數(shù)據(jù)庫(kù)支持的內(nèi)容,我可能還用用上tinyint、文本和mediumtext數(shù)據(jù)類型。

發(fā)出如下指令來(lái)建立表格:
CREATE TABLE Products
(prod_id INT(16), prod_color VARCHAR(20), prod_descr VARCHAR(255), prod_size DECIMAL(8,2));

如果這些指令順利完成,你就可以在表格中正常地插入信息。你可以參到文章SQL基礎(chǔ)一:數(shù)據(jù)查詢"得到詳細(xì)說(shuō)明。

除了數(shù)據(jù)類型,你還可以在創(chuàng)建表格時(shí)定義自動(dòng)增量字段(auto-incremented field)、關(guān)鍵字、索引和特殊數(shù)值限制。在表格定義時(shí),這些參數(shù)與數(shù)據(jù)類型一同傳遞。如果在創(chuàng)建表格Product時(shí)定義具有特殊數(shù)值限制的自動(dòng)增量prod_id,命令如下:
CREATE TABLE Products
(prod_id INT(16)AUTO_INCREMENT, prod_color VARCHAR(20), prod_descr VARCHAR(255), prod_size DECIMAL(8,2), UNIQUE (`prod_id`));

如果把prod_id做為索引字段定義,可以用CREATE INDEX
CREATE INDEX ProdIndex ON Product (prod_id);

這里有必要重申:數(shù)據(jù)庫(kù)提供商在關(guān)鍵字的處理上有所不同。所以,具體情況請(qǐng)參考你的數(shù)據(jù)庫(kù)提供商的文檔。

關(guān)于索引的更多內(nèi)容:

索引是一個(gè)比較深的課題。除了介紹有關(guān)關(guān)鍵字和索引的理論,Builder.com的供稿人Eric Roland寫(xiě)了幾篇很好的文章,你可以通過(guò)它們來(lái)學(xué)到更多的相關(guān)知識(shí)。

修改表格 
當(dāng)你開(kāi)始對(duì)表格進(jìn)行操作時(shí),你也許覺(jué)得有必要修改表格的結(jié)構(gòu)、字段類型等等。在前面,我強(qiáng)烈建議你避免在生產(chǎn)環(huán)境(production environment)這么做。因?yàn)橛行┎僮鳎缣砑?、刪除和修改字段可能會(huì)刪除或破壞相關(guān)字段中的數(shù)據(jù)。

好,現(xiàn)在讓我們看看如何修改表格。首先,在表格Product中加入一欄。你可以指定該欄插入的相對(duì)其它欄的位置,也可以讓它插到表格末端(默認(rèn)):
ALTER TABLE Product ADD prod_name VARCHAR(20) AFTER prod_id;

用類似的語(yǔ)句刪除一個(gè)欄目:
ALTER TABLE Product DROP prod_size;

最后,更改一個(gè)欄目的數(shù)據(jù)類型:
ALTER TABLE Product CHANGE prod_color prod_color_id INT(20);

現(xiàn)在,你的表格如表C所示:


欄目名稱:
 prod_id
 prod_name
 prod_color_id
 prod_descr 
數(shù)據(jù)類型:
 Int(16)
 Varchar(20)
 Int(20)
 Varchar(255))
注意,有些數(shù)據(jù)庫(kù)不支持關(guān)鍵字DROP。另外,如果你改變現(xiàn)有的某一欄的數(shù)據(jù)類型,大多數(shù)數(shù)據(jù)庫(kù)會(huì)試圖轉(zhuǎn)化該欄目現(xiàn)有數(shù)據(jù)的數(shù)據(jù)類型。然而,如果是轉(zhuǎn)為一個(gè)不支持的數(shù)據(jù)類型,數(shù)據(jù)就有可能丟失。舉例來(lái)說(shuō),如果把一個(gè)類型為Varchar的包含人名字的字段改為Int類型,轉(zhuǎn)換的結(jié)果可能是整型的默認(rèn)值。

刪除表格和數(shù)據(jù)庫(kù)
在刪除表格和數(shù)據(jù)庫(kù)之前,你需要確保丟失這些數(shù)據(jù)不會(huì)造成惡果。如果你刪除數(shù)據(jù)庫(kù),庫(kù)中的所有表格和內(nèi)容都會(huì)被清除。如果你刪除一個(gè)表格,表格中的所有內(nèi)容都會(huì)丟失,但是庫(kù)中的其它表格沒(méi)有影響。

在刪除表格或整個(gè)欄目之前,你必須清楚數(shù)據(jù)庫(kù)的結(jié)構(gòu)。如果你進(jìn)入一個(gè)已經(jīng)存在的數(shù)據(jù)庫(kù)并錯(cuò)誤刪除了某個(gè)元素,可能會(huì)影響到促發(fā)條件(?trigger)、存儲(chǔ)過(guò)程和視圖。有些數(shù)據(jù)庫(kù)支持用關(guān)鍵字RESTRICTCASCADE去預(yù)防由于刪除表格帶來(lái)的損失。RESTRICT一般按默認(rèn)設(shè)置,預(yù)防丟失表格,而CASCADE用于刪除與該表格有關(guān)的實(shí)體。

現(xiàn)在上面建立的表格Product是可以被刪除的,我們開(kāi)始刪除它:
DROP TABLE Product;

現(xiàn)在刪除數(shù)據(jù)庫(kù):
DROP DATABASE Catalog;
大多數(shù)數(shù)據(jù)庫(kù)軟件提供商支持DROP DATABASE命令,盡管它是在SQL99標(biāo)準(zhǔn)中被定義而不是SQL92。

部分?jǐn)?shù)據(jù)庫(kù)提供了FLUSH命令,該命令可以讓你刪除表格中的內(nèi)容但又可以保持表格的結(jié)果,:
FLUSH TABLE Product;

如你所見(jiàn),刪除數(shù)據(jù)庫(kù)中的主要結(jié)構(gòu)并丟失所存的所有數(shù)據(jù)的容易程度令人難以想象,所以,一定要小心使用這些命令,而當(dāng)你不清楚數(shù)據(jù)庫(kù)中的內(nèi)容時(shí),就不要使用這些命令。
數(shù)據(jù)庫(kù)管理
在前一篇文章中,你學(xué)會(huì)了如何在一個(gè)或多個(gè)表格中查找數(shù)據(jù)?,F(xiàn)在,你學(xué)會(huì)了如何把你操作數(shù)據(jù)庫(kù)結(jié)構(gòu)。你學(xué)會(huì)了創(chuàng)建、修改并銷毀表格和數(shù)據(jù)。這些都是設(shè)計(jì)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的應(yīng)用程序的必須用的操作。

跟我學(xué)SQL()串行數(shù)據(jù)類型

SQL的數(shù)據(jù)類型決定了一個(gè)字段的內(nèi)容在數(shù)據(jù)庫(kù)中會(huì)被如何處理、存儲(chǔ)和顯示。SQL92定義了標(biāo)準(zhǔn)的數(shù)據(jù)類型,目的是給數(shù)據(jù)庫(kù)制造商建立自己的數(shù)據(jù)類型提供藍(lán)圖。在前面的文章中,我們介紹了一些常用的數(shù)據(jù)類型,這些數(shù)據(jù)類型分為四大類:
串行
數(shù)值
日期時(shí)間
區(qū)間型
 
本文將向你概述這些數(shù)據(jù)類型在數(shù)據(jù)庫(kù)中是如何使用的,然后著重解釋串行數(shù)據(jù)類型。這些信息可以作為有用的參考,或者作為關(guān)于某個(gè)數(shù)據(jù)庫(kù)制造商具體產(chǎn)品中數(shù)據(jù)類型的背景知識(shí)。

使用數(shù)據(jù)類型
當(dāng)你在數(shù)據(jù)庫(kù)中創(chuàng)建了一個(gè)表格,你就定義了每列的名字以及要輸入到這些列中的內(nèi)容的數(shù)據(jù)類型。從先前的文章中借用一個(gè)例子:

CREATE TABLE Products
(prod_id INT(16)AUTO_INCREMENT, prod_color VARCHAR(20),
prod_descr VARCHAR(255), prod_size DECIMAL(8,2),
UNIQUE (`prod_id`));

在以上的查詢中,定義行prod_color VARCHAR(20)發(fā)出指令要?jiǎng)?chuàng)建一個(gè)列,名字是prod_color,數(shù)據(jù)類型是VARCHAR,長(zhǎng)度為20

你的數(shù)據(jù)庫(kù)使用和每個(gè)類型相關(guān)的描述符來(lái)區(qū)別數(shù)據(jù)類型。例如,VARCHAR數(shù)據(jù)類型的描述符所含的信息將它區(qū)別為串行數(shù)據(jù)型,它包含所有的串字符,其長(zhǎng)度是可變的。數(shù)據(jù)庫(kù)里列的定義還包含了其他信息,例如對(duì)應(yīng)于數(shù)據(jù)類型的特定長(zhǎng)度。

如前所述,每個(gè)數(shù)據(jù)庫(kù)制造商都希望在SQL92定義的標(biāo)準(zhǔn)上建立自己的數(shù)據(jù)類型。這樣每個(gè)數(shù)據(jù)庫(kù)在定義數(shù)據(jù)類型時(shí)都能夠設(shè)定自己所需要的最大容量限制和其他屬性。許多數(shù)據(jù)庫(kù)使用的數(shù)據(jù)類型名字和這里列出來(lái)的一樣,盡管每種的實(shí)現(xiàn)方法都有微小的差別。要確定特定數(shù)據(jù)類型使用方法的細(xì)節(jié)最好的方法還是查閱數(shù)據(jù)庫(kù)制造商的文檔。

已經(jīng)說(shuō)過(guò)了,希望對(duì)標(biāo)準(zhǔn)字符串?dāng)?shù)據(jù)類型有更多的了解就往下看。


 
有兩種主要的串行數(shù)據(jù)類型:字符和位。串行使用數(shù)據(jù)庫(kù)里由SQL_TEXT所定義的字符。SQL_92標(biāo)準(zhǔn)同時(shí)還提供了NATIONAL CHARACTER(國(guó)家字符集)和NATIONAL CHARACTER VARYING(國(guó)家字符集變體),這兩者都能使用可定義字符集。后者的處理方法和CHARACTER以及CHARACTER VARYING類型一樣。

CHARACTER | CHAR
使用方法:CHARACTER(clength) | CHAR(clength)

CHARACTERCHAR這兩個(gè)關(guān)鍵字是相同的。
CHARACTER
類型一個(gè)突出的特點(diǎn)是它們能夠包含<space(空白)>這個(gè)字符。
CHARACTER
類型包含了固定長(zhǎng)度的串字符(來(lái)自SQL_TEXT的語(yǔ)言集),clength。
<space>
字符在值的長(zhǎng)度小于clength時(shí)起填充作用。這表示CHARACTER字段的長(zhǎng)度是固定的。
你可以把CHARACTER的數(shù)據(jù)類型字段和相同類型的其他允許不同長(zhǎng)度的字段比較,或者和CHARACTER VARYING 數(shù)據(jù)類型比較。
有些數(shù)據(jù)庫(kù)允許和數(shù)值數(shù)據(jù)類型比較。
CHARACTER VARYING | CHAR VARYING | VARCHAR
使用方法:CHARACTER VARYING(maxlength) | CHAR VARYING(maxlength) | VARCHAR(maxlength)

CHARACTER VARYING,CHAR VARYING,和VARCHAR這幾個(gè)關(guān)鍵字是相同的。
這些類型能容納最大長(zhǎng)度的字符串,maxlength。
數(shù)據(jù)庫(kù)把字段的長(zhǎng)度作為值的實(shí)際長(zhǎng)度。
你可以把這些數(shù)據(jù)類型的字段和相同類型的其他允許不同最大長(zhǎng)度的字段比較。
BIT

使用方法:BIT(blength)

這種類型包含了帶有長(zhǎng)度的位字符(10),blength。例如,如果我們使用BIT(2),樣本值將為“01”。
有的數(shù)據(jù)庫(kù)會(huì)在串的開(kāi)頭插入空位,其的則會(huì)填充它們以符合固定長(zhǎng)度的要求。
位字符是串,不是整數(shù)。
你可以把BIT數(shù)據(jù)類型的字段與相同類型的允許不同長(zhǎng)度的其它字段比較,或者和BIT VARYING數(shù)據(jù)類型比較。
有些數(shù)據(jù)庫(kù)允許BITSCHARACTER或者INTEGER類型比較。
BIT VARYING

使用方法: BIT VARYING(maxlength)

這種類型包含了最大長(zhǎng)度的位字符,maxlength
所記錄的長(zhǎng)度被設(shè)為值的實(shí)際長(zhǎng)度。
數(shù)據(jù)庫(kù)允許和其的BIT VARYING數(shù)據(jù)字段比較,或者和BIT的數(shù)據(jù)字段比較。
對(duì)我們的SQL系列有了一些了解了嗎?

請(qǐng)把你的評(píng)論、問(wèn)題或者回應(yīng)發(fā)到下面的討論欄,或者如果你有關(guān)于SQL基礎(chǔ)系列的論題,可以發(fā)到我們編輯的信箱。

串理論
數(shù)據(jù)庫(kù)生產(chǎn)商通過(guò)建立這些基礎(chǔ)的數(shù)據(jù)類型來(lái)創(chuàng)建你實(shí)際要實(shí)現(xiàn)的數(shù)據(jù)類型。對(duì)于字符串,這就可能包括相同名字的(不同)類型,例如CHARBIT,或者擴(kuò)展到包括TEXTSMALL TEXT,以及包含字符串的其他數(shù)據(jù)類型。

數(shù)據(jù)從一個(gè)數(shù)據(jù)庫(kù)遷移到另一個(gè)數(shù)據(jù)庫(kù)時(shí),這種設(shè)計(jì)上的彈性產(chǎn)生了一個(gè)必須克服的障礙。在一個(gè)數(shù)據(jù)庫(kù)里,你可能會(huì)有一個(gè)叫做CHAR的類型,這個(gè)類型所允許的最大容量大于你要遷移到的數(shù)據(jù)庫(kù)的最大容量。而且,(SQL92)標(biāo)準(zhǔn)中沒(méi)有明確定義的類型可能會(huì)變化較大,這樣的話只用遵從慣例來(lái)簡(jiǎn)化遷移。

ZDNet China最近的文章《BLOB移植的替換方案》中討論了存在數(shù)據(jù)類型移植問(wèn)題時(shí)保護(hù)數(shù)據(jù)的一個(gè)可能的解決方案。SQL標(biāo)準(zhǔn)沒(méi)要包括存儲(chǔ)二進(jìn)制數(shù)據(jù)的指標(biāo),這造成了不同數(shù)據(jù)庫(kù)制造商產(chǎn)品間的不兼容。軟件開(kāi)發(fā)者必須找到提到方案列清除這些障礙。

在這個(gè)系列的下一篇文章中,我們會(huì)看看SQL92的數(shù)字?jǐn)?shù)據(jù)類型,每個(gè)有什么特點(diǎn),以及對(duì)要實(shí)現(xiàn)這些類型的數(shù)據(jù)庫(kù)的要求

跟我學(xué)SQL()從子表里刪除數(shù)據(jù)

在這篇文章里我要描述一下如何從表格里刪除列,要?jiǎng)h除的這些列同時(shí)還要依賴于其他表格的標(biāo)準(zhǔn)。要解決這個(gè)問(wèn)題就需要一個(gè)很聰明而且完全遵守SQL92子查詢聲明的應(yīng)用程序。  
我必須提醒讀者的是,盡管查詢可能會(huì)遵守SQL的標(biāo)準(zhǔn),但是眾多的數(shù)據(jù)庫(kù)生產(chǎn)商會(huì)以不同的句法支持實(shí)現(xiàn)SQL。以下這個(gè)解決方案應(yīng)該適合于大多數(shù)數(shù)據(jù)庫(kù);但是,如果你的結(jié)果有出入,就還是應(yīng)該查看一下文檔。同時(shí),由于這個(gè)查詢要處理DELETE聲明,所以你應(yīng)該在將其應(yīng)用于真實(shí)的生產(chǎn)環(huán)境以前在實(shí)驗(yàn)數(shù)據(jù)上進(jìn)行測(cè)試。

需要更多的背景信息?
查看這些文章就能快速上路:
SQL基礎(chǔ)I查數(shù)據(jù)查詢》涉及到了DELETE查詢的使用。
《使用SQL子選項(xiàng)來(lái)合并查詢》說(shuō)明子選項(xiàng)查詢能夠減少對(duì)數(shù)據(jù)庫(kù)請(qǐng)求的數(shù)量,并提供了例子。
SQL基礎(chǔ):查詢多個(gè)表》提供了更多關(guān)于子選項(xiàng)的信息,還講到了使用單個(gè)查詢就能訪問(wèn)多個(gè)表格的多種其他方法。

寵物店的例子
要解釋如何進(jìn)行這種類型的列刪除,我會(huì)使用如下這個(gè)數(shù)據(jù)庫(kù)的表格,該數(shù)據(jù)庫(kù)叫做PetStore,并包含有清單(inventory)信息。在叫做品種(breed的表A里,我存儲(chǔ)有每種動(dòng)物的信息和寵物店庫(kù)存的信息。在叫做清單的表B里,包含有商店里特定動(dòng)物的信息。

在這個(gè)例子里,我們先假設(shè)商店把整窩Shitzu小狗都賣(mài)完了。我可以使用breed表格里的breed_id字段來(lái)刪除Shitzu清單里的所有項(xiàng)目,就像這樣:

DELETE FROM inventory WHERE breed_id IN
(SELECT breed_id FROM breed WHERE breed_name = ‘Shitzu’);

首先,我要指定需要?jiǎng)h除記錄的表格,在這里是清單表格。然后再將識(shí)別字段breed_id同子選項(xiàng)子句的結(jié)果反復(fù)比對(duì)。我知道要找的是Shitzus,所以就能直接刪掉他們,而不用再在單獨(dú)的請(qǐng)求里查詢breed_id

我必須要警告你的是,以這種方式使用DELETE聲明是危險(xiǎn)的,只有在你對(duì)數(shù)據(jù)庫(kù)的結(jié)構(gòu)很熟悉的情況下才能使用這些聲明。DELETE查詢會(huì)從受影響的表格里刪除掉全部列,你應(yīng)該知道這對(duì)你所管理著的數(shù)據(jù)意味著什么。有個(gè)好辦法是使用SELETE *這個(gè)短語(yǔ)替代DELETE關(guān)鍵字來(lái)對(duì)DELETE聲明的子查詢結(jié)果進(jìn)行測(cè)試,這樣就能保證結(jié)果里含有你要?jiǎng)h除的所有東西,就像這樣:

SELECT * FROM inventory WHERE breed_id IN
(SELECT breed_id FROM breed WHERE breed_name = ‘Shitzu’);

DELETEJOIN聯(lián)用
有人問(wèn)到了解決這個(gè)問(wèn)題另一個(gè)可能的辦法:把JOIN子句和DELETE聲明聯(lián)合使用。由于以前沒(méi)有使用過(guò)這種方法,我就研究了一下,發(fā)現(xiàn)SQL Server的文檔聲明支持這個(gè)方法,盡管它不符合SQL92。在經(jīng)過(guò)測(cè)試和詢問(wèn)各種數(shù)據(jù)庫(kù)平臺(tái)的老手之后,我發(fā)現(xiàn)把DELETEJOIN聲明聯(lián)合使用在我測(cè)試過(guò)的任何平臺(tái)上都行不通。

從多個(gè)表格里一次刪除
以上的解決方案還沒(méi)有解釋如何使用父表從多個(gè)子表里刪除信息。但是SQL92規(guī)范里沒(méi)有提供完成這項(xiàng)任務(wù)的標(biāo)準(zhǔn)解決方案。

DELETE的聲明不能把多個(gè)表格作為一個(gè)參數(shù)接受。作為一個(gè)具有破壞性的查詢,這能保證在命令要被執(zhí)行的地方不會(huì)出現(xiàn)歧義。此外,這個(gè)限制防止了在單個(gè)聲明內(nèi)將AND和多個(gè)子查詢聯(lián)用。如果測(cè)試SELECT聲明的結(jié)果用以檢查DELETE查詢將要影響到的是哪些數(shù)據(jù),你會(huì)發(fā)現(xiàn)SELECT會(huì)返回多個(gè)表格的清單,DELETE不會(huì)影響到的多個(gè)子查詢不在其中。

有很多可能的方法能夠滿足你的需求,例如在表格里創(chuàng)建一個(gè)字段,用以指明該項(xiàng)目是否為活動(dòng)的?;蛘撸憧梢允褂靡恍?shù)據(jù)庫(kù)里的預(yù)存程序在每個(gè)所需的DELETE查詢里迭代。

跟我學(xué)SQL()數(shù)值數(shù)據(jù)類型

SQL92標(biāo)準(zhǔn)定義了若干種基本數(shù)據(jù)類型,它們是SQL數(shù)據(jù)庫(kù)中各種數(shù)據(jù)類型的基礎(chǔ)。在《字符串?dāng)?shù)據(jù)類型》一文中,我們已經(jīng)詳細(xì)討論了SQL92標(biāo)準(zhǔn)所定義的字符串?dāng)?shù)據(jù)類型。現(xiàn)在,我們來(lái)進(jìn)一步討論數(shù)值數(shù)據(jù)類型。  
你最好開(kāi)始嘗試使用不同數(shù)據(jù)庫(kù)實(shí)現(xiàn)方法并在它們傳遞數(shù)據(jù),這樣可以加深你對(duì)數(shù)值數(shù)據(jù)類型的理解。本文將給你一個(gè)數(shù)值數(shù)據(jù)類型的概要,你可以結(jié)合你的數(shù)據(jù)庫(kù)的文檔資料來(lái)學(xué)習(xí)。

在字符串、數(shù)值、datetimeinterval這四種數(shù)據(jù)類型中,數(shù)值型的種類最多,約束也最多。在不同數(shù)據(jù)庫(kù)實(shí)現(xiàn)方法之間交換數(shù)據(jù)時(shí),數(shù)值型的精度也最容易降低。OracleSQL服務(wù)器之間的實(shí)現(xiàn)分歧(同樣的數(shù)據(jù)類型長(zhǎng)度不同)導(dǎo)致它們之間的數(shù)據(jù)傳遞過(guò)程會(huì)截短數(shù)字、改變它們的數(shù)值。因此,在移植程序前,你有必須很明確的了解兩個(gè)平臺(tái)間的數(shù)據(jù)定義差異,以及危及數(shù)據(jù)精度的風(fēng)險(xiǎn)。

謹(jǐn)記上述警告后,讓我們看看SQL92標(biāo)準(zhǔn)的數(shù)值類型

基本數(shù)值類型
與數(shù)值有關(guān)的類型統(tǒng)稱為數(shù)值類型。所有的數(shù)值都有精度,精度指的是有效數(shù)字位數(shù)。有的數(shù)值還有標(biāo)度值(scale value),它用來(lái)指示小數(shù)點(diǎn)右邊的最小有效數(shù)字位數(shù)。例如,數(shù)字1234.56的精度為6,標(biāo)度值為2,可以定義為NUMERIC(6,2)。

每一個(gè)數(shù)據(jù)庫(kù)實(shí)現(xiàn)方法都有關(guān)于如何近似數(shù)值或者截短數(shù)值的規(guī)則。除了提供獲取數(shù)值長(zhǎng)度和其它數(shù)值處理所需的屬性外,SQL92提供了內(nèi)建函數(shù),如加、減、乘、除等。所有的數(shù)值類型之間都可以互相比較、互相賦值。盡管實(shí)現(xiàn)方法不同,但是它們有一個(gè)的共同點(diǎn),即它們的結(jié)果一般都保留最大精度。

NUMERIC

用法:NUMERIC(精度,標(biāo)度值)

是一種精確數(shù)值類型,即它是數(shù)字的值的文字表示。(可以對(duì)該數(shù)字進(jìn)行取舍或者截取以符合指定精度,標(biāo)度值由預(yù)定義的規(guī)則確定。)
為了符合標(biāo)度值指定的小數(shù)數(shù)字位數(shù),舍去多余的小數(shù)部分,舍入過(guò)程采用十進(jìn)制。
數(shù)字的總長(zhǎng)度等于精度,如果標(biāo)度值大于0(有小數(shù)部分),則長(zhǎng)度加1
小數(shù)部分的位數(shù)要符合標(biāo)度值。
DECIMAL | DEC
用法:DECIMAL(精度,標(biāo)度值) | DEC(精度,標(biāo)度值)

是一種精確數(shù)值類型。
用十進(jìn)制。
數(shù)字的總長(zhǎng)度等于精度,如果標(biāo)度值大于0(有小數(shù)部分),則長(zhǎng)度加1。
小數(shù)部分的位數(shù)不得小于標(biāo)度值,小數(shù)位數(shù)的上限由數(shù)據(jù)庫(kù)提供商設(shè)定。

INTEGER | INT
用法: INTEGER(精度)

是一種精確數(shù)值類型。
使用二進(jìn)制或者十進(jìn)制,這基于表示該數(shù)值的二進(jìn)制位(bit)的個(gè)數(shù)(這是implementation-specific,與SMALLINT對(duì)應(yīng))。
標(biāo)度值恒為0
數(shù)據(jù)庫(kù)供應(yīng)商對(duì)其定義了最大精度和最小精度。
供應(yīng)商可能會(huì)提供的默認(rèn)精度。
SMALLINT
用法:SMALLINT(精度)

是一種精確數(shù)值類型。
位數(shù)取舍方法與INTEGER (二進(jìn)制或者十進(jìn)制)相同。
標(biāo)度值恒為0。
最大精度等于或者小于INTEGER的最大精度。
FLOAT
用法:FLOAT(精度)

是一種近似數(shù)值類型,即對(duì)一個(gè)指定的數(shù)值用指數(shù)形式表示出來(lái),如1.23e-45(等于),該數(shù)值類型的取舍和截短方法大多由數(shù)據(jù)庫(kù)提供商定義。
當(dāng)取舍時(shí),使用二進(jìn)制精度。
精度表示使用的最小位數(shù),最大精度由數(shù)據(jù)庫(kù)提供商設(shè)定。
REAL
用法:REAL

是一種近似數(shù)值類型。
使用二進(jìn)制精度,最大精度由數(shù)據(jù)庫(kù)提供商設(shè)定。
其默認(rèn)精度必須小于DOUBLE PRECISION的默認(rèn)精度。
DOUBLE PRECISION
用法: DOUBLE PRECISION

是一種近似數(shù)值類型。
使用二進(jìn)制精度,最大精度由數(shù)據(jù)庫(kù)提供商設(shè)定。
其默認(rèn)精度必須大于PRECISION的默認(rèn)精度。
相關(guān)理論
數(shù)據(jù)庫(kù)提供商在基本數(shù)據(jù)類型的基礎(chǔ)上創(chuàng)建了你實(shí)際需要的數(shù)據(jù)類型。對(duì)數(shù)值類型來(lái)說(shuō),它可以包括同名的數(shù)據(jù)類型,如INT、REAL,也包括為了滿足特定場(chǎng)合或者用途而創(chuàng)建的新數(shù)據(jù)類型。

在我們的下一篇文章,我們將討論datetimeinterval數(shù)據(jù)類型。

跟我學(xué)SQL()datetimeinterval數(shù)據(jù)類型

datetimeinterval是兩種與時(shí)間有關(guān)的數(shù)據(jù)類型。它們的作用體現(xiàn)在以下幾個(gè)方面:創(chuàng)建或者更改記錄庫(kù)中的某條記錄、當(dāng)某個(gè)時(shí)間發(fā)生時(shí)運(yùn)行記錄、或者計(jì)算某個(gè)datetime變量建立后所經(jīng)歷過(guò)的時(shí)間。本文將介紹SQL92標(biāo)準(zhǔn)對(duì)上述兩種數(shù)據(jù)類型的描述。

 SQL數(shù)據(jù)類型

如果你想進(jìn)一步了解SQL數(shù)據(jù)類型,請(qǐng)閱讀SQL基礎(chǔ):字符串型數(shù)據(jù)類型,這篇文章的范圍覆蓋了SQL中的通用數(shù)據(jù)類型并說(shuō)明了各種字符串?dāng)?shù)據(jù)類型的用法,SQL基礎(chǔ):數(shù)字?jǐn)?shù)據(jù)類型詳細(xì)介紹了數(shù)字?jǐn)?shù)據(jù)類型。

 Datetime
用于表示時(shí)間或者日期的數(shù)據(jù)類型都屬于datetime類型。每一種datetime數(shù)據(jù)類型都有他自己的用于獲取值的長(zhǎng)度和它所保存信息的手段,如天、月、分鐘、秒、秒的小數(shù)等等。

實(shí)際上,datetime的實(shí)現(xiàn)形式隨著定義它的標(biāo)準(zhǔn)不同而擁有不同的長(zhǎng)度和格式;然而,各個(gè)公司定義的類型都內(nèi)在地符合下述規(guī)則。舉例來(lái)說(shuō),時(shí)標(biāo)(timestamp)的某個(gè)實(shí)現(xiàn)可能沒(méi)有分隔符,隨著細(xì)節(jié)的規(guī)范不同,長(zhǎng)度和格式也發(fā)生變化,在某些場(chǎng)合以空格做為間隔符。Datetime數(shù)據(jù)類型包括:DATA、TIMETIMESTAMP。讓我們仔細(xì)研究這些分類,首先我們看看DATA。

DATA
用法:DATA

DATA類型允許沒(méi)有參數(shù),如精度。
DATA
的字段包括年、月和日。
DATA
的長(zhǎng)度為十個(gè)字符: YYYY-MM-DD。(Y表示年、M表示月、D表示日。)
它只允許與其它DATA類型字段相比較。
允許的數(shù)字必須符合公歷的規(guī)范。
TIME
用法:TIME(精度)

該類型包含了小時(shí)、分和秒,格式為hh:mm:ssh表示小時(shí)、m表示分、s表示秒)
精度可選擇,(……
時(shí)間以世界標(biāo)準(zhǔn)時(shí)間(Universal Coordinated Time,UTC)為準(zhǔn),即00:00:00表示.格林威治的午夜,服務(wù)器的時(shí)區(qū)隱含的。
如果不需要秒的小數(shù)部分,那么TIME的長(zhǎng)度為八個(gè)字符。否則就是八位長(zhǎng)度在加上精度:hh:mm:ss.p。
它只能與其它TIME類型數(shù)據(jù)進(jìn)行比較。
如果沒(méi)有指定精度,精度默認(rèn)為0

TIME WITH TIME ZONE

  用法:TIME (精度) WITH TIME ZONE

這個(gè)值要符合TIME數(shù)據(jù)類型
TIMEZONE
部分表示相對(duì)UTC的時(shí)差:00:00:00+hh:mm。它的范圍為-12:5913:00
精度表示秒的小數(shù)部分。
帶有TIMEZONETIME長(zhǎng)度為14個(gè)字符加上精度,在加上一個(gè)分隔符。
只可以與帶有TIMEZONETIME類型數(shù)據(jù)進(jìn)行比較
TIMESTAMP

用法:TIMESTAMP(精度)

該類型包含有年、月、日、時(shí)、分、秒,格式為:YYYY-MM-DD hh:mm:ss.。
可以包括秒的小數(shù)部分,這由定義的精度決定。
它的日期部分符合公歷標(biāo)準(zhǔn),時(shí)間部分為UTC格式。默認(rèn)為當(dāng)?shù)貢r(shí)區(qū)。
時(shí)標(biāo)的長(zhǎng)度為19個(gè)字符,加上精度,在加上精度分隔符。
許多系統(tǒng)偏離上述定義的長(zhǎng)度,如UNIX風(fēng)格時(shí)標(biāo)格式為:,YYYY-MM-DD hh:mm:ss.p
如果沒(méi)有定義精度,默認(rèn)值為6,但是許多數(shù)據(jù)庫(kù)公司默認(rèn)為0,所以請(qǐng)參考你的開(kāi)發(fā)文檔。
時(shí)標(biāo)只可以與其它TIMESTAMP類型的值相比較。
TIMESTAMP WITH TIME ZONE

用法:TIMESTAMP(精度)WITH TIME ZONE

時(shí)標(biāo)部分符合上述TIMESTAWP的規(guī)則。
精度代表秒的小數(shù)部分。
時(shí)區(qū)部分的要求和TIME WITH TIME ZONE一樣,即時(shí)區(qū)符合UTC規(guī)范,范圍在-12:59 +13:00之間。
總長(zhǎng)度為25個(gè)字符,加上精度,加上一個(gè)精度分隔符:YYYY-MM-DD hh:mm:ss.p。
它只能與其它TIMESTAMP WITH TIME ZONE類型的數(shù)據(jù)進(jìn)行比較。
Interval

Interval用于表示時(shí)間尺度。例如,你可以用操作符(將在下面進(jìn)行解釋)去計(jì)算兩個(gè)日期間天數(shù)并加以保存。

各個(gè)公司在處理interval上有很大的不同——有些公司提供不同的度量單位,如年或者分鐘,而有些公司在根本就不支持interval。SQL92標(biāo)準(zhǔn)的interval類型只提供一種子類型:INTERVAL

INTERVAL

用法: INTERVAL (限定語(yǔ))

有兩種類型的interval:一種為年份-月份,即保存年份和月份(YYYY-MM);一種為天-時(shí)間DD HH:MM:SS),用來(lái)保存天數(shù)、小時(shí)、分鐘和秒。
限定語(yǔ)——在某些數(shù)據(jù)庫(kù)中interval前導(dǎo)精度(lead precision——根據(jù)其值來(lái)指示interval采用年份-月份還是天-時(shí)間方式。
interval
可正可負(fù)。
當(dāng)與其它interval類型變量相比較時(shí),結(jié)果保持最大精度,如有必要?jiǎng)t補(bǔ)零。
INTERVAL
全部由整數(shù)組成,除了含有小數(shù)的秒之外。
 “
年份-月份類型的interval變量只能與其它的年份-月份interval變量進(jìn)行比較。天-時(shí)間類型也與此類似。
操作符

操作結(jié)果類型

當(dāng)處理日期時(shí)間時(shí),時(shí)區(qū)保持不變——盡管有些數(shù)據(jù)庫(kù)為了比較而將其中的一個(gè)時(shí)區(qū)轉(zhuǎn)換為另一個(gè)。存在一些操作關(guān)鍵字,如OVERLAPSEXTRACT,它們用于操作和比較datetime類型數(shù)據(jù)。然而,不同的數(shù)據(jù)庫(kù)在這些操作關(guān)鍵字用法和支持方式上有著很大的不同。

OVERLAPS用于計(jì)算時(shí)間交疊的跨度,其操作對(duì)象可以是兩個(gè)datetime也可以是一個(gè)datetime和一個(gè)intervalEXTRACT用于提取datetime或者interval類型數(shù)據(jù)的某個(gè)部分,如在DATA類型數(shù)據(jù)中提取月份。

數(shù)據(jù)類型
由于已建立的標(biāo)準(zhǔn)是為了各公司在現(xiàn)有基礎(chǔ)上實(shí)現(xiàn)實(shí)際上的數(shù)據(jù)類型的,因此在具體限制、參數(shù)和數(shù)據(jù)類型等方面,你還是需要經(jīng)常參考你的數(shù)據(jù)庫(kù)文檔。


全面接觸SQL語(yǔ)法(1)

SQL功能與特性 通過(guò)SQL命令,程序設(shè)計(jì)師或數(shù)據(jù)庫(kù)管理員(DBA)可以:
  (一)建立數(shù)據(jù)庫(kù)的表格。(包括設(shè)置表格所可以使用之空間)
 ?。ǘ└淖償?shù)據(jù)庫(kù)系統(tǒng)環(huán)境設(shè)置。
 ?。ㄈ┽槍?duì)某個(gè)數(shù)據(jù)庫(kù)或表格,授予用戶存取權(quán)限。
 ?。ㄋ模?duì)數(shù)據(jù)庫(kù)表格建立索引值。
  (五)修改數(shù)據(jù)庫(kù)表格結(jié)構(gòu)。(新建、刪除或是修改表格字段)
 ?。?duì)數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)的新建。
  (七)對(duì)數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)的刪除。
  (八)對(duì)數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)的修改。
  (九)對(duì)數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)的查詢。
  這幾項(xiàng)便是通過(guò)SQL命令可以完成的事情,看起來(lái)是不是比起查詢兩個(gè)字所代表的功能要多的多了呢?

  SQL語(yǔ)法的分類

  其實(shí)SQL命令并不是非常多,可是要把SQL用到出神入化,卻也只需要短短幾個(gè)命令便夠,因?yàn)?span lang="EN-US">SQL命令是針對(duì)關(guān)系型數(shù)據(jù)庫(kù)所建立出來(lái)的語(yǔ)法敘述,所以SQL在這類數(shù)據(jù)庫(kù)中所發(fā)揮的功能非常的強(qiáng),以下將針對(duì)在VB中常用的SQL語(yǔ)法基本命令加以分類介紹。在說(shuō)明SQL的命令以及使用語(yǔ)法之前,以下將SQL做了的分類,在致上SQL語(yǔ)法所使用到的類型,可以說(shuō)都已包含在這些類別當(dāng)中。

  第一類、屬性詞(Predicates)  在SQL命令中用來(lái)指明所要選擇的記錄的方式。如ALL、TOPDISTINCT等等。

  第二類、聲明(Declaration)  針對(duì)SQL ParameterParameter Query 的名稱與數(shù)據(jù)類型做聲明,如PARAMETERS的聲明等等。

  第三類、條件子句(Clause)  在SQL的查詢中,利用一些表達(dá)式定義出查詢的條件,以縮小尋找的范圍,如WHERE。

  第四類、運(yùn)算符(Operator)與操作數(shù)(Operation)  在SQL的查詢中,與Operation共同組成表達(dá)式(Expression),如BETWEEN....AND 運(yùn)算符與INNER JOIN操作數(shù)。

  第五類、函數(shù)(Function)  一些SQL常見(jiàn)的函數(shù),像是AVG()是求算數(shù)平均數(shù)的函數(shù)。

  第六類、SQL語(yǔ)句(Statement)  SQL的語(yǔ)句,可以說(shuō)是SQL語(yǔ)法的主體,用來(lái)對(duì)某一個(gè)特定的數(shù)據(jù)庫(kù)發(fā)出指示,并返回相關(guān)的數(shù)據(jù),而SQL的語(yǔ)法結(jié)構(gòu),基本上可以利用下面的式子來(lái)表示:命令+條件子句

  例如:  SELECT*FROM TAB WHERE TAB.NAME='A'

  其中的“FROM....WHERE”便是一個(gè)條件子句,其實(shí)SQL的語(yǔ)法并不難,您只需記住這樣的一個(gè)規(guī)則,相信可以很快的了解SQL用法。

  SQL語(yǔ)法與命令

SELECT 語(yǔ)句
SELECT[predicate]{*|table.*|[table.]field [,[table.]field2[,...]]} [AS alias1 [,alias2[,...]]]
FROM tableexpression [,...][IN externaldatabase]  [WHERE...]  [GROUP BY...]  [HAVING...] [ORDER BY...]
[WITH OWNERACCESS OPTION]
SELECT
語(yǔ)句包括下面幾個(gè)部分
predicate 
如前面所述,包括了ALL,DISTINCT,DISTINCTROW,TOP 我們可以利用這樣的語(yǔ)句去限制查詢后所得的結(jié)果。

  *  從指定表格中指定所有的字段。

  table  針對(duì)被選擇出的記錄的字段,所指定表格的名稱。

  field1,field2  想要讀取數(shù)據(jù)的字段名稱,如果包含了一個(gè)以上的字段,會(huì)依照列出的順序來(lái)讀取數(shù)據(jù)。

  alias1,alias2  用來(lái)替代在表格實(shí)際字段名稱的化名。

  tableexpression  表格名稱或包含我們所想要的數(shù)據(jù)的表格。

  externaldatabase  若使用到不是目前的數(shù)據(jù)庫(kù)則將其名字定義在externaldatabase當(dāng)中。
    ALL,DISTINCT,DISTINCTROW,TOP屬性詞用法

  SELECT [ALL|DISTINCT|DISTINCTROW|[TOP n[PERCENT]]] FROM table

  ALL  若是您不指定任何的字段數(shù)據(jù),則Microsoft Jet數(shù)據(jù)庫(kù)引擎(database engine)將會(huì)選擇所有的字段,并依據(jù)所定的條件查詢出需求數(shù)據(jù)集。

例如下面這兩個(gè)例子將會(huì)具有相同的效果,都會(huì)從職員表格中返回所有字段的數(shù)據(jù)。

  例如:  若是我們要查詢出職員表格中的所有記錄,可以通過(guò)下面的語(yǔ)句來(lái)完成。

SELECT ALL* FROM 職員表格; DISTINCT

    對(duì)某個(gè)表格所選擇的字段數(shù)據(jù),略過(guò)重復(fù)的情況,也就是說(shuō),針對(duì)某個(gè)字段查詢出來(lái)的記錄結(jié)果是唯一的。例如有許多存放在職員表格的職員數(shù)據(jù),也許會(huì)具有相同的姓名,所以若是我們用SQL語(yǔ)句中的SELECT DISTINCT,則查詢出來(lái)的結(jié)果將會(huì)針對(duì)不一樣的姓名加以篩選。若是您把

  DISTINCT 加以省略,則這樣的查詢會(huì)顯示所有的記錄。

  DISTINCTROW  將整條記錄重復(fù)的記錄忽略掉,而不是只有針對(duì)某一個(gè)字段的數(shù)據(jù)。

  table  指定查詢記錄所需要的表格。

  例如:  SELECT DISTINCTROW 公司名稱  FROM 顧客表格 INNER JOIN 訂單表格  ON 顧客表格.顧客ID=訂單表格.顧客ID

  ORDER BY 公司名稱;

  如果您忽略 DISTINCTROW 則會(huì)對(duì)每個(gè)公司產(chǎn)生一行以下的訂單數(shù)據(jù)。此外,若是DISTINCTROW只有用在一個(gè)表格當(dāng)中,則會(huì)被省略掉。

  TOP  從第一條或最后一條開(kāi)始(利用ORDER BY條件子句),返回特定條數(shù)的數(shù)據(jù)。

  例如:  當(dāng)您想要知道在2000年,班上前25名的學(xué)生姓名數(shù)據(jù)時(shí),您可以輸入這樣的語(yǔ)句:

  SELECT TOP 25 學(xué)生姓名  FORM 學(xué)生表格  WHERE 畢業(yè)年份=1994  ORDER BY 畢業(yè)成績(jī)平均分?jǐn)?shù) DESC;

  如果您沒(méi)有加上ORDER BY 這行條件的話,您所得到的數(shù)據(jù),將會(huì)隨機(jī)的數(shù)據(jù)。此外,在TOP語(yǔ)句之后,除了可以加上數(shù)字以外,還可以利用保留字PERCENT來(lái)查詢。

  例如:  SELECT TOP 10 PERCENT學(xué)生姓名

  FROM學(xué)生表格  WHERE畢業(yè)年份=1994  ORDER BY畢業(yè)成績(jī)平均DESC
    PARAMETERS(參數(shù))聲明的用法

  對(duì)于參數(shù)型的查詢語(yǔ)法中,對(duì)參數(shù)的名稱以及數(shù)據(jù)類型作 聲明的操作。

  PARAMETERS name datatype[,name datatype[,...]]

  name  PARAMETERS的名稱。您可以把參數(shù)名稱當(dāng)作字符串來(lái)使用,若是名稱中包含了空字符串,可以利用中括號(hào)來(lái)處理,例如:“VBeden”。

  datatype  輸入?yún)?shù)的數(shù)據(jù)類型。

  例如: 若是您在查詢時(shí),需要機(jī)動(dòng)的輸入姓名 ,可以利用下列的方式完成:

  PARAMETERS “輸入姓名” Text;

  SELECT*  FROM 職員表格  WHERE姓名=“輸入姓名:

ORDER BY條件語(yǔ)句

  此條件子句,通常與SELECT語(yǔ)句合并使用目的是將查詢的結(jié)果,依照指定字段加以排序。

  SELECT fieldlist  FROM table  WHERE selectcriteria  ORDER BY field[ASC|DESC][,field2[ASC|DESC][,...]]

  fieldlist  欲查詢的字段名稱。其中可以與ALL,DISTINCT,DISINCTROW,或TOP一起來(lái)使用。

  table  欲查詢的表格名稱。

  selectcriteria  查詢的標(biāo)準(zhǔn)設(shè)置。

  field1  指定要依照那個(gè)字段作為排序的依據(jù),若是你沒(méi)有加上ORDER BY查詢出的數(shù)據(jù)集將不會(huì)作排序的操作。

  ASC  遞增順序類別。(默認(rèn)值)

  DESC  遞減順序類別。

  例如:  或是我們要將輸出數(shù)據(jù)依據(jù)出生的先后次序排列,可以利用下面的命令。

  SELECT 姓名,生日  FROM 職員表格  ORDER BY 生日

  SELECT LastName,FirstName  FROM Employees  ORDER BY LastName ASC;

  IN 條件子句

  指定要速勝哪一個(gè)外部數(shù)據(jù)庫(kù)的表格。(必須是Microsoft Jet數(shù)據(jù)庫(kù)引擎所可以連接的數(shù)據(jù)庫(kù),如dBase,Paradox等等)

  SELECT|INSERT]INTO destination IN  {path|["path" "type"]|[""[type;DATABASE=path]]}
FROM tableexpression IN  {path|["path" "type"]|[""[type;DATABASE=path]]}
destination
  欲插入數(shù)據(jù)的外部表格名稱。

  tableexpression  表格名稱或是被讀取數(shù)據(jù)的表格名稱。這個(gè)參數(shù)可以是一個(gè)單一的表格名稱,或是一段已經(jīng)被存儲(chǔ)的SQL查詢等。

  path  包含該表格的完整路徑名稱。

  type  數(shù)據(jù)庫(kù)的類型名稱, 通常是當(dāng)數(shù)據(jù)庫(kù)部屬于Jet database時(shí)才會(huì)使用。(例如:dBASE III,dBASE IV,Paradox 3.x,Paradox 4.x, Btrieve)

  例如:下面這兩段的意義相同

PartA....FROM Table  IN ""[dBASE IV;DATABASE=C:\DBASE\DATA\SALES;];

PartB....FROM Table   IN "C:\DBASE\DATA\SALES" "dBASE IV;"

   例如:Microsoft Jet database

SELECT 顧客編號(hào)   FROM 顧客表格   IN CUSTOMER.MDB   WHERE 顧客編號(hào) Like "A*";
其中CUSTOMER.MDBO Jet database 的數(shù)據(jù)庫(kù)名稱,其中包含了顧客表格。

例如:dBASE III or IV
SELECT
顧客編號(hào)   FROM 顧客表格  IN "C:\DBASE\DATA\SALES" "dBASE IV;"  WHERE 顧客編號(hào) Like "A*";
所以當(dāng)我們使用不同于ACCESS 的數(shù)據(jù)庫(kù)時(shí),必須指明該數(shù)據(jù)庫(kù)的類型名稱。

HAVING 條件子句

  指定一特定的分組記錄,并滿足HAVING 所指定的條件或狀態(tài),但條件是針對(duì)分組的條件設(shè)置。

SELECT fieldlist  FROM table   WHERE selectcriteria  GROUP BY groupfieldlist  HAVING groupcriteria
fieldlist
顯示被查詢的字段名稱。(可與ALL,DISTINCT,DISTINCTROW,或TOP相結(jié)合)
table 
欲查詢數(shù)據(jù)的表格名稱。
selectcriteria  
選取標(biāo)準(zhǔn)。
groupfieldlist 
分組記錄的字段名稱,到多10個(gè)字段。而這些字段的順序決定最高到最低的分組階層。
groupcriteria 
決定什么樣的分組記錄要被顯示。
HAVING
WHERE 的用法相當(dāng)類似,不同之處在于HAVING必須用于GROUP之后的分組數(shù)據(jù)上。
例如:
SELECT
分類編,Sum(庫(kù)存數(shù)量)  FROM 產(chǎn)品表格   GROUP BY 分類編號(hào)  HAVING Sum(庫(kù)存數(shù)量)>100 AND 產(chǎn)品名稱 LIKE "*";

  GROUP BY 條件子句

  依據(jù)指定的字段,將具有相同數(shù)值的記錄合并成一條。

SELECT fieldlist  FROM table  WHERE criteria  GROUP BY groupfieldlist
fieldlist 
欲讀取的字段名稱。(可與ALL,DISTINCT,DISTINCTROW,或TOP合并使用)
table 
被查詢的表格名稱。
groupfieldlist 
分組記錄的字段名稱,到多10個(gè)字段,而這些字段的順序決定最高到最低的分組層次。
例如:
SELECT
姓名,Count(姓名)AS 職員姓名  FROM 職員表格   WHERE 部門(mén)名稱='業(yè)務(wù)部'  GROUP BY 姓名

  FROM 條件子句

  指定表格名稱或是查詢,其中包含列在SELECT語(yǔ)句的字段數(shù)據(jù)。

SELECT fieldlist  FROM tableexpression[IN externaldatabase]
fieldlist 
表格中的字段名稱。(可與ALL,DISTINCT,DISTINCTROW,TOP相結(jié)合)
tableexpression 
表格名稱,或多個(gè)表格的算式。
externaldatabase 
若該表格參考到外部的數(shù)據(jù)庫(kù)時(shí),將其完整的路徑名稱記下。
例如:從職員表格下,查詢出所有姓名字段的數(shù)據(jù)(只有姓名字段被查詢,其他則不顯示)。
SELECT
姓名 FROM 職員表格;

  WHERE 條件子句

  指定查詢的條件與限制。

SELECT fieldlist  FROM tableexpression  WHERE criteria
fieldlist
字段名稱。(可與ALL,DISTINCT,DISTINCTROW,TOP相結(jié)合)
tableexpression 
表格名稱,或多個(gè)表格的算式。
criteria 
查詢的結(jié)果,必須依照這一限制標(biāo)準(zhǔn)。
例如:要查詢出職員表格中,所有姓氏是李的數(shù)據(jù),可以用下面的語(yǔ)句。
SELECT
姓名 FROM 職員表格 WHERE 姓氏='';

BETWEEN...AND 運(yùn)算符

  決定某一人數(shù)值是否介于特定的范圍之內(nèi),此運(yùn)算符只可以用在SQL的語(yǔ)句中。

expr[Not]BETWEEN value1 AND value2
expr 
指定要加以計(jì)算的字段與表達(dá)式的組合。
value1,value2 
所指明的數(shù)值范圍。
例如:若是要從職員表格查詢出所有年齡介于25-30歲的員工,可以利用下面的程序來(lái)做。
SELECT
姓名,年齡 BETWEEN 25 AND 30  FROM 職員表格;

  LIKE 操作數(shù)

  用來(lái)將一字符串與另一特定字符串樣式(pattern)比較,并將符合該字符串樣式的記錄過(guò)濾出來(lái)。

expression LIKE "pattern"
expression 
使用在WHERE條件子句,SQL表達(dá)式。
pattern  
用以比較的字符串樣式。
例如:若是你要查詢出所有以為首的姓氏,可以利用下面的式子。
Like "
*"
LIKE
操作數(shù)的多種范例:
1
、多個(gè)字符:
(1)"a*a"  
可篩選:"aa","aBa","aBBBa",不能篩選:"aBC"
(2)"*ab*"  
可篩選:"abc","AABB","Xab",不能篩選:"aZb","bac"
2
、特殊字符:   "a“*”a"   可篩選:"a*a",不能篩選:"aaa"
3
、單一字符:   "a?a"      可篩選:"aaa","a3a","aBa",不能篩選:"aBBBa"
4
、單一數(shù)字:  "a#a"   可篩選:"a0a","a1a","a2a",不能篩選:"aaa","a10a"
5
、字符范圍:   "“a-z”"  可篩選:"f","p","j",不能篩選:"2","&"
6
、指定字符以外部范圍:  "“!a-z”"    

7、指定非數(shù)字:  "“!0-9”"  可篩選:"A","a","&","~",不能篩選:"0","1","9"
8
、組合式結(jié)構(gòu):  "a“!b-m”#"   可篩選:"An9","az0","a99",不能篩選:"abc","aj0"

   SQL數(shù)字函數(shù)

  1、AVG:算數(shù)平均數(shù)

  AVG(expr)

  Expr  字段名稱或表達(dá)式。

  例如:  若要計(jì)算職員身高超過(guò)165厘米的職員平均身高,可以利用下面的SQL語(yǔ)句來(lái)完成。

  SELECT Avg(身高)  AS 平均身高  FROM 職員表格 WHERE 身高>165;

  2、COUNT:計(jì)算記錄條數(shù)

  COUNT(expr)

  expr  字段名稱或表達(dá)式。

  例如:  若是要統(tǒng)計(jì)出業(yè)務(wù)部門(mén)的職員人數(shù),并查詢出職員的姓名,可以利用下面的程序。

  SELECT Count(姓名) AS 職員姓名  FROM 職員表格  WHERE 部門(mén)名稱='業(yè)務(wù)部';

  3FIRSTLAST:返回某字段的第一條數(shù)據(jù)與最后一條數(shù)據(jù)。

  FIRST(expr)  LAST(expr)

  expr  字段名稱或表達(dá)式。

  例如:  若是要找出貨品數(shù)量字段的第一條數(shù)據(jù)與貨品價(jià)格字段的最后一條數(shù)據(jù)時(shí),可以利用下面的查詢方式。

  SELECT FIRST(貨品數(shù)量)LAST(貨品價(jià)格)  FROM 訂單表格

  4、MAX,與MIN:返回某字段的最大值與最小值。

  用法同FIRSTLAST。

  5、SUM:返回某特定字段或是運(yùn)算的總和數(shù)值。

  SUM(expr)

  expr  字段名稱或表達(dá)式。

  例如:  要計(jì)算出貨品總價(jià),可使用下面的程序。

  SELECT  Sum(單位價(jià)格*貨品數(shù)量)  AS 貨品總價(jià) FROM 訂單表格

  多層SQL查詢

  顧名思義,多層的SQL查詢的便在于:在一個(gè)SQL語(yǔ)句中可以包含另一個(gè)SQL查詢語(yǔ)句,形成內(nèi)部嵌套的查詢類型。

comparison[ANY|ALL|SOME](sqlstatement)
expression[NOT]IN (sqlstatement)
[NOT]EXISTS(sqlstatement)
comparison   
將表達(dá)式與內(nèi)層查詢的結(jié)果比較的操作。
expression   
對(duì)內(nèi)層查詢的結(jié)果作搜索的表達(dá)式。
sqlstatement   
SELECT語(yǔ)句構(gòu)成的SQL查詢,必須用()將該語(yǔ)句括起來(lái)。

   例如:  我們先從訂單表格當(dāng)中,查詢出所有的單位,再將產(chǎn)品表格中的單位與的一一對(duì)比,查詢出所有高于訂單表格的單位價(jià)格的記錄。

  SELECT * FROM 產(chǎn)品表格  WHERE 單位價(jià)格>ANY (SELECT 單位價(jià)格 FROM 訂單表格 WHERE 折扣>=.25);

SQL與數(shù)據(jù)庫(kù)的維護(hù)
  表格的建立

  將SQL中的基本語(yǔ)法作了一番介紹以后,但大多是偏向于數(shù)據(jù)庫(kù)數(shù)據(jù)的查詢與過(guò)濾,但實(shí)際上,我們通過(guò)SQL命令所可以做的事還有很多,接下來(lái)要介紹的便是如何利用SQL的語(yǔ)法命令來(lái)建立一個(gè)數(shù)據(jù)庫(kù)中的表格。

   CREATE TABLE語(yǔ)句

  我們可以利用這個(gè)命令,來(lái)建立一個(gè)全新的表格,但前提則是:數(shù)據(jù)庫(kù)必須已經(jīng)存在。

CREATE TABLE table(field1 type[(size)][index1][,field2 type[(size)][index2][,...]][,nultifieldindex[,...]])
table   
欲建立的新的表格名稱。
field1,field2    
在新表格中的新的字段名稱,到少要一個(gè)字段以上。
type  
字段的數(shù)據(jù)類型。
size    
字段的大小。
index1,index2    
利用CONSTRAINT條件子句定義一個(gè)單一字段的索引名稱。
multifieldindex  
利用CONSTRAINT條件子句定義一個(gè)多重字段的索引名稱。

  例如:  建立一個(gè)擁有職員姓名與部門(mén)字段的表格。

CREATE TABLE 職員表格 (姓名TEST,部門(mén)TEST,職員編號(hào) INTEGER CONSTRAINT職員字段索引PRIMARY KEY)
在這一個(gè)范例中,我們建立了一個(gè)表格名稱為職員表格的表格,并且定義了該表格的主鍵值,以限制數(shù)據(jù)不能重復(fù)輸入。

  表格索引的建立

   CREATE INDEX語(yǔ)句  這個(gè)命令主要是對(duì)一個(gè)已存在的表格建立索引,其用法如下:

CREATE[UNIQUE]INDEX index ON table(field[ASC|DESC][,field[ASC|DESC],...])[WITH {PRIMARY|DISALLOWNULL|IGNORENULL}]
index 
  欲被建立的索引名稱。

table  欲建立索引的表格名稱。

  field  欲被建立的索引的字段名稱。并可通過(guò)DESC保留字,來(lái)決定索引的順序。

  例如:在職員表格中建立一個(gè)索引。
CREATE INDEX
新索引名稱   ON 職員表格(姓名部門(mén))
 表格的字段更新
CONSTRAINT
條件子句
CONSTRAINT
的功能是類似索引(INDEX)的,雖然CONSTRAINT 也可以建立表格之間的關(guān)聯(lián)性。
單一字段索引:
CONSTRAINT name{PRIMARY KEY|UNIQUE|REFERENCES foreigntable[(foreignfield1,foreignfield2)]}
多字段索引:
CONSTRAINT name
{PRIMARY KEY(primary1[,primary2[,...]])
|UNIQUE(unique1[,unique2[,...]])
|FOREIGN KEY (ref1[,ref2[,...]])
|REFERENCES foreigntable[(foreignfield1[,foreignfield2[,...]])]}
name   
要被建立的CONSTRAINT名稱。
primary1,primary2   
被用來(lái)設(shè)計(jì)成主鍵值的字段名稱(可一個(gè)以上)。
unique1,unique2   
被用來(lái)設(shè)計(jì)成唯一鍵值的字段名稱(可一個(gè)以上)
foreign key  
字段名稱,或是參考到別的表格中字段的字段名稱。
foreigntable   
如前所述,被參考到的表格。
foreignfield1,foreignfield2    
在參考到的表格當(dāng)中,被ref1,ref2字段所指定的字段。如果被參考的字段是參考表格中的主鍵值,你也可以省略這個(gè)條件子句。
例如:  當(dāng)我們要建立一個(gè)新的職員數(shù)據(jù)表格,表格包含姓名、部門(mén)名稱與生日三個(gè)字段,且由這三個(gè)字段建立一個(gè)唯一的索引時(shí),可以使用下面這段SQL的語(yǔ)句。
CREATE TABLE
職員數(shù)據(jù)表格
(
姓名 TEST,部門(mén)名稱 TEST,生日 DATETIME,CONSTRAINT 職員數(shù)據(jù)表格限制 UNIQUE(姓名,部門(mén)名稱,生日));
以上是SQL中,與數(shù)據(jù)庫(kù)表格建立相關(guān)的命令,你可以利用這些命令,通過(guò)SQL的語(yǔ)句,將數(shù)據(jù)庫(kù)表格完整的建立出來(lái),接下來(lái)的章節(jié),將針對(duì)數(shù)據(jù)庫(kù)建立之后的維護(hù)與增刪所要使用的SQL語(yǔ)句作一介紹。

表的刪除

   DELETE語(yǔ)句  我們可以利用DELETE語(yǔ)句,將表格中的記錄刪除。(注意:記錄被刪除后,無(wú)法再?gòu)?fù)原,所以條件設(shè)置要正確)

DELETE[table.*]  FROM tableexpression   WHERE criteria
table  
欲刪除記錄的表格名稱,也可以用*來(lái)取代。
tableexpression 
一個(gè)或一個(gè)以上表格的名稱。此一參數(shù)可以為單一的表格名稱或是從INNER JOIN,LEFT JOIN,或RIGHTJOIN 等運(yùn)算所得到的結(jié)果。
criteria  
決定表格中記錄要被刪除的標(biāo)準(zhǔn)。

  例如:  若是我們要將職員表格中姓名姓名叫做'李名'的記錄刪除,我們可以利用下面的SQL語(yǔ)句來(lái)完成。

  DELETE * FROM 職員表格  WHERE 姓名='李名';
    數(shù)據(jù)庫(kù)表格相關(guān)的操作命令

  SQL除了可以作為查詢與數(shù)據(jù)庫(kù)表格的建立的工具外,對(duì)于數(shù)據(jù)庫(kù)與表格的新建、刪修、與維護(hù),與具有相當(dāng)不錯(cuò)的功能,若是讀者使用SQL命令得宜,對(duì)于整個(gè)效率的提高有著很大的幫助,所以對(duì)于SQL語(yǔ)句所帶來(lái)的優(yōu)勢(shì),常常會(huì)遇到一個(gè)情況,就是:當(dāng)我們對(duì)多個(gè)表格作復(fù)雜與多步驟的處理時(shí),或許SQL只要一個(gè)語(yǔ)句就可以完成所有的需求與目標(biāo),乍看一下,或許覺(jué)得有些玄妙,但是接下來(lái)的章節(jié),會(huì)讓你了解其中的妙處。

  SELECT...INTO語(yǔ)句  我們可以通過(guò)這個(gè)命令,利用既存表格查詢,來(lái)建立一個(gè)新表格的查詢語(yǔ)句。

SELECT field1[,field2[,...]]INTO newtable[IN externaldatabase]  FROM source
field1,field2   
欲拷貝到新表格的字段名稱。
newtable  
欲建立之新表格的名稱,不可是已經(jīng)存在的表格。
externaldatabase  
若是該表格在另外的外部數(shù)據(jù)庫(kù)時(shí),該數(shù)據(jù)庫(kù)的名稱。
source   
記錄數(shù)據(jù)拷貝的來(lái)源表格名稱,可以是單一的表格或是一段SQL查詢之語(yǔ)句。
例如:你可以通過(guò)下面的SQL語(yǔ)句,來(lái)建立一個(gè)新的訓(xùn)練名冊(cè)表格。
SELECT
職員表格.姓名,職員表格.部門(mén)  INTO 訓(xùn)練名冊(cè) FROM 職員表格   WHERE 職稱='新進(jìn)人員';

  INNER JOIN操作數(shù)

  當(dāng)某一個(gè)共同的字段數(shù)據(jù)相等時(shí),將兩個(gè)表格的記錄加以組合。

SELECT fields  FROM table1 INNER JOIN table2  ON table1.field1 compopr table2.field2
table1,table2  
欲進(jìn)行記錄組合的表格名稱。
field1,field2  
欲組合的字段名稱。(必須具有相同的數(shù)據(jù)類型)
compopr  
比較關(guān)系運(yùn)算符如下:“=”“<”,“>”“<=”,“<>”等。
例如:若是你要把分類表格與產(chǎn)品表格作組合,可參考下面的SQL語(yǔ)句。
SELECT
分類名稱,產(chǎn)品名稱   FROM 分類表格 INNER JOIN 產(chǎn)品表格   ON 分類表格.分類編號(hào)=產(chǎn)品表格.分類編號(hào);

  UNION操作數(shù)

  我們可以通過(guò)UNION操作數(shù)來(lái)建立連接的查詢條件,UNION操作數(shù)可以將兩個(gè)以上的表格或是查詢的結(jié)果組合起來(lái)。

[TABLE]query1 UNION [ALL][TABLE]query2 [UNION [ALL]  [TABLE]queryn [...]]
query1,query2,queryn 
為一個(gè)SELECT的語(yǔ)句,或是一個(gè)已存在的查詢名稱,或是一個(gè)已存在的表格名稱。

  例如:  你可以利用下面的SQL語(yǔ)句,將訂單數(shù)量超過(guò)1000的顧客表格記錄,與新客戶表格作UNION的操作。

TABLE 新客戶表格 UNION ALL  SELECT *   FROM 顧客表格   WHERE 訂單數(shù)量>1000;
   ALTER語(yǔ)句  在一個(gè)表格被建立之后,利用ALTER語(yǔ)句,我們可以去修改表格的字段設(shè)計(jì)。

ALTER TABLE table
{ADD {COLUMN field type[(size)][CONSTRAINT index]
|CONSTRAINT multifieldindex}
|DROP {COLUMN field|CONSTRAINT indexname}}
table  
欲被ALTER的表格名稱。
field 
要被增加或刪除的字段名稱。
type  
字段數(shù)據(jù)類型。
size  
字段大小。
index   
對(duì)此字段的索引。
例如:在職員表格中新建一個(gè)薪水的字段。
ALTER TABLE
職員表格   ADD COLUMN 薪水 CURRENCY;
例如:在職員表格中刪除一個(gè)薪水的字段。
ALTER TABLE
職員表格 DROP COLUMN 薪水;

  DROP語(yǔ)句  針對(duì)所指定的表格或字段加以刪除,或是把索引刪除。

DROP {TABLE table|INDEX index ON table}
table 
欲刪除之表格或索引依附之表格名稱。
index  
欲從表格中刪除的索引名稱。
例如:從職員表格中,刪除編號(hào)索引。
DROP INDEX MyIndex ON Employees;
例如:從數(shù)據(jù)庫(kù)中,刪除整個(gè)表格。
DROP TABLE
職員表格;

  INSERT INTO語(yǔ)句  新建一條數(shù)據(jù)到表格當(dāng)中。

  多條記錄新建查詢:

INSERT INTO target [IN externaldatabase][(field1[,field2[,...]])]
SELECT [source.]field1[,field2[,...]    FROM tableexpression
單條記錄新建查詢:
INSERT INTO target[(field1[,field2[,...]])]   VALUES(value1[,value2[,...]]
target 
新建記錄的表格名稱。
externaldatabase  
外部數(shù)據(jù)庫(kù)的路徑,搭配IN條件子句使用。
source   
若是記錄從其它表格中拷貝時(shí),指明該表格的名稱。
field1,field2  
欲增加數(shù)據(jù)的字段名稱。
tableexpression 
表格名稱或描述記錄是從哪一個(gè)表格中插入的表格名稱。配合INNER JOIN,LEFT JOIN,或 RIGHT JOIN 運(yùn)算符一起使用。
value1,value2  
欲插入表格中的數(shù)值。
例如:在客戶數(shù)據(jù)表格中,從新的表格插入數(shù)據(jù)。
INSERT INTO
客戶數(shù)據(jù)表格   SELECT 新客戶數(shù)據(jù)表格.*   FROM 新客戶數(shù)據(jù)表格;
例如:在職員表格中插入數(shù)據(jù)。
INSERT INTO
職員表格(姓名,生日,職稱)  VALUES("王榮","57/12/11","經(jīng)理");
例如:從訓(xùn)練人員表格中,將職員雇用時(shí)間超過(guò)30天者,加入到正式職員表格中。
INSERT INTO
職員表格   SELECT 訓(xùn)練人員表格.*   FROM 訓(xùn)練人員表格   WHERE 雇用天數(shù)>30;

   UPDATE語(yǔ)句

  建立一個(gè)UPDATE的查詢,通過(guò)條件的限制來(lái)修改特定的數(shù)據(jù)。

UPDATE table  SET newvalue   WHERE criteria;
table 
欲修改數(shù)據(jù)的表格名稱。
newvalue 
欲修改成的數(shù)值(將該項(xiàng)數(shù)值插入到特定的字段當(dāng)中)。
criteria 
查詢條件,用來(lái)決定要修改哪些記錄。
例如: 若是要把訂單表格中的訂單數(shù)量修改成1.1倍,運(yùn)費(fèi)為1.03倍,可利用下列之SQL語(yǔ)句來(lái)完成。
UPDATE
訂單表格  SET 訂單數(shù)量=訂單數(shù)量 * 1.1,運(yùn)費(fèi)=運(yùn)費(fèi) * 1.03  WHERE 運(yùn)達(dá)地點(diǎn)='美國(guó)'
當(dāng)我們完成修改后,你可以利用 SELECT 語(yǔ)句,配合同樣的 WHERE 條件子句,來(lái)察看修改的數(shù)據(jù)是否正確。
事實(shí)上,要利用SQL完成某些看似復(fù)雜的操作,并不需要繁瑣的SQL命令組合,或是許許多多的步驟才能完成,其實(shí)最重要的還是要活用SQL命令,才會(huì)在最精簡(jiǎn)的SQL語(yǔ)句里獲得最高的效率。


五種提高 SQL 性能的方法

 

時(shí),為了讓?xiě)?yīng)用程序運(yùn)行得更快,所做的全部工作就是在這里或那里做一些很小調(diào)整。啊,但關(guān)鍵在于確定如何進(jìn)行調(diào)整!遲早您會(huì)遇到這種情況:應(yīng)用程序中的 SQL 查詢不能按照您想要的方式進(jìn)行響應(yīng)。它要么不返回?cái)?shù)據(jù),要么耗費(fèi)的時(shí)間長(zhǎng)得出奇。如果它降低了報(bào)告或您的企業(yè)應(yīng)用程序的速度,用戶必須等待的時(shí)間過(guò)長(zhǎng),他們就會(huì)很不滿意。就像您的父母不想聽(tīng)您解釋為什么在深更半夜才回來(lái)一樣,用戶也不會(huì)聽(tīng)你解釋為什么查詢耗費(fèi)這么長(zhǎng)時(shí)間。(對(duì)不起,媽媽,我使用了太多的 LEFT JOIN。)用戶希望應(yīng)用程序響應(yīng)迅速,他們的報(bào)告能夠在瞬間之內(nèi)返回分析數(shù)據(jù)。就我自己而言,如果在 Web 上沖浪時(shí)某個(gè)頁(yè)面要耗費(fèi)十多秒才能加載(好吧,五秒更實(shí)際一些),我也會(huì)很不耐煩。

為了解決這些問(wèn)題,重要的是找到問(wèn)題的根源。那么,從哪里開(kāi)始呢?根本原因通常在于數(shù)據(jù)庫(kù)設(shè)計(jì)和訪問(wèn)它的查詢。在本月的專欄中,我將講述四項(xiàng)技術(shù),這些技術(shù)可用于提高基于 SQL Server? 的應(yīng)用程序的性能或改善其可伸縮性。我將仔細(xì)說(shuō)明 LEFT JOIN、CROSS JOIN 的使用以及 IDENTITY 值的檢索。請(qǐng)記住,根本沒(méi)有神奇的解決方案。調(diào)整您的數(shù)據(jù)庫(kù)及其查詢需要占用時(shí)間、進(jìn)行分析,還需要大量的測(cè)試。這些技術(shù)都已被證明行之有效,但對(duì)您的應(yīng)用程序而言,可能其中一些技術(shù)比另一些技術(shù)更適用。

INSERT 返回 IDENTITY

我決定從遇到許多問(wèn)題的內(nèi)容入手:如何在執(zhí)行 SQL INSERT 后檢索 IDENTITY 值。通常,問(wèn)題不在于如何編寫(xiě)檢索值的查詢,而在于在哪里以及何時(shí)進(jìn)行檢索。在 SQL Server 中,下面的語(yǔ)句可用于檢索由最新在活動(dòng)數(shù)據(jù)庫(kù)連接上運(yùn)行的 SQL 語(yǔ)句所創(chuàng)建的 IDENTITY 值:

SELECT @@IDENTITY

這個(gè) SQL 語(yǔ)句并不復(fù)雜,但需要記住的一點(diǎn)是:如果這個(gè)最新的 SQL 語(yǔ)句不是 INSERT,或者您針對(duì)非 INSERT SQL 的其他連接運(yùn)行了此 SQL,則不會(huì)獲得期望的值。您必須運(yùn)行下列代碼才能檢索緊跟在 INSERT SQL 之后且位于同一連接上的 IDENTITY,如下所示:

INSERT INTO Products (ProductName) VALUES ('Chalk')

SELECT @@IDENTITY

在一個(gè)連接上針對(duì) Northwind 數(shù)據(jù)庫(kù)運(yùn)行這些查詢將返回一個(gè)名稱為 Chalk 的新產(chǎn)品的 IDENTITY 值。所以,在使用 ADO Visual Basic? 應(yīng)用程序中,可以運(yùn)行以下語(yǔ)句:

Set oRs = oCn.Execute("SET NOCOUNT ON;INSERT INTO Products _

(ProductName) VALUES ('Chalk');SELECT @@IDENTITY")

lProductID = oRs(0)

此代碼告訴 SQL Server 不要返回查詢的行計(jì)數(shù),然后執(zhí)行 INSERT 語(yǔ)句,并返回剛剛為這個(gè)新行創(chuàng)建的 IDENTITY 值。SET NOCOUNT ON 語(yǔ)句表示返回的記錄集有一行和一列,其中包含了這個(gè)新的 IDENTITY 值。如果沒(méi)有此語(yǔ)句,則會(huì)首先返回一個(gè)空的記錄集(因?yàn)?span lang="EN-US"> INSERT 語(yǔ)句不返回任何數(shù)據(jù)),然后會(huì)返回第二個(gè)記錄集,第二個(gè)記錄集中包含 IDENTITY 值。這可能有些令人困惑,尤其是因?yàn)槟鷱膩?lái)就沒(méi)有希望過(guò) INSERT 會(huì)返回記錄集。之所以會(huì)發(fā)生此情況,是因?yàn)?span lang="EN-US"> SQL Server 看到了這個(gè)行計(jì)數(shù)(即一行受到影響)并將其解釋為表示一個(gè)記錄集。因此,真正的數(shù)據(jù)被推回到了第二個(gè)記錄集。當(dāng)然您可以使用 ADO 中的 NextRecordset 方法獲取此第二個(gè)記錄集,但如果總能夠首先返回該記錄集且只返回該記錄集,則會(huì)更方便,也更有效率。

此方法雖然有效,但需要在 SQL 語(yǔ)句中額外添加一些代碼。獲得相同結(jié)果的另一方法是在 INSERT 之前使用 SET NOCOUNT ON 語(yǔ)句,并將 SELECT @@IDENTITY 語(yǔ)句放在表中的 FOR INSERT 觸發(fā)器中,如下面的代碼片段所示。這樣,任何進(jìn)入該表的 INSERT 語(yǔ)句都將自動(dòng)返回 IDENTITY 值。

CREATE TRIGGER trProducts_Insert ON Products FOR INSERT AS

    SELECT @@IDENTITY

GO

觸發(fā)器只在 Products 表上發(fā)生 INSERT 時(shí)啟動(dòng),所以它總是會(huì)在成功 INSERT 之后返回一個(gè) IDENTITY。使用此技術(shù),您可以始終以相同的方式在應(yīng)用程序中檢索 IDENTITY 值。

內(nèi)嵌視圖與臨時(shí)表

某些時(shí)候,查詢需要將數(shù)據(jù)與其他一些可能只能通過(guò)執(zhí)行 GROUP BY 然后執(zhí)行標(biāo)準(zhǔn)查詢才能收集的數(shù)據(jù)進(jìn)行聯(lián)接。例如,如果要查詢最新五個(gè)定單的有關(guān)信息,您首先需要知道是哪些定單。這可以使用返回定單 ID SQL 查詢來(lái)檢索。此數(shù)據(jù)就會(huì)存儲(chǔ)在臨時(shí)表(這是一個(gè)常用技術(shù))中,然后與 Products 表進(jìn)行聯(lián)接,以返回這些定單售出的產(chǎn)品數(shù)量:

CREATE TABLE #Temp1 (OrderID INT NOT NULL, _

                     OrderDate DATETIME NOT NULL)

INSERT INTO #Temp1 (OrderID, OrderDate)

SELECT     TOP 5 o.OrderID, o.OrderDate

FROM Orders o ORDER BY o.OrderDate DESC

SELECT     p.ProductName, SUM(od.Quantity) AS ProductQuantity

FROM     #Temp1 t

    INNER JOIN [Order Details] od ON t.OrderID = od.OrderID

    INNER JOIN Products p ON od.ProductID = p.ProductID

GROUP BY p.ProductName

ORDER BY p.ProductName

DROP TABLE #Temp1

這些 SQL 語(yǔ)句會(huì)創(chuàng)建一個(gè)臨時(shí)表,將數(shù)據(jù)插入該表中,將其他數(shù)據(jù)與該表進(jìn)行聯(lián)接,然后除去該臨時(shí)表。這會(huì)導(dǎo)致此查詢進(jìn)行大量 I/O 操作,因此,可以重新編寫(xiě)查詢,使用內(nèi)嵌視圖取代臨時(shí)表。內(nèi)嵌視圖只是一個(gè)可以聯(lián)接到 FROM 子句中的查詢。所以,您不用在 tempdb 中的臨時(shí)表上耗費(fèi)大量 I/O 和磁盤(pán)訪問(wèn),而可以使用內(nèi)嵌視圖得到同樣的結(jié)果:

SELECT p.ProductName,

    SUM(od.Quantity) AS ProductQuantity

FROM     (

    SELECT TOP 5 o.OrderID, o.OrderDate

    FROM     Orders o

    ORDER BY o.OrderDate DESC

    ) t

    INNER JOIN [Order Details] od ON t.OrderID = od.OrderID

    INNER JOIN Products p ON od.ProductID = p.ProductID

GROUP BY

    p.ProductName

ORDER BY

    p.ProductName

此查詢不僅比前面的查詢效率更高,而且長(zhǎng)度更短。臨時(shí)表會(huì)消耗大量資源。如果只需要將數(shù)據(jù)聯(lián)接到其他查詢,則可以試試使用內(nèi)嵌視圖,以節(jié)省資源。

避免 LEFT JOIN NULL

當(dāng)然,有很多時(shí)候您需要執(zhí)行 LEFT JOIN 和使用 NULL 值。但是,它們并不適用于所有情況。改變 SQL 查詢的構(gòu)建方式可能會(huì)產(chǎn)生將一個(gè)花幾分鐘運(yùn)行的報(bào)告縮短到只花幾秒鐘這樣的天壤之別的效果。有時(shí),必須在查詢中調(diào)整數(shù)據(jù)的形態(tài),使之適應(yīng)應(yīng)用程序所要求的顯示方式。雖然 TABLE 數(shù)據(jù)類型會(huì)減少大量占用資源的情況,但在查詢中還有許多區(qū)域可以進(jìn)行優(yōu)化。SQL 的一個(gè)有價(jià)值的常用功能是 LEFT JOIN。它可以用于檢索第一個(gè)表中的所有行、第二個(gè)表中所有匹配的行、以及第二個(gè)表中與第一個(gè)表不匹配的所有行。例如,如果希望返回每個(gè)客戶及其定單,使用 LEFT JOIN 則可以顯示有定單和沒(méi)有定單的客戶。

此工具可能會(huì)被過(guò)度使用。LEFT JOIN 消耗的資源非常之多,因?yàn)樗鼈儼c NULL(不存在)數(shù)據(jù)匹配的數(shù)據(jù)。在某些情況下,這是不可避免的,但是代價(jià)可能非常高。LEFT JOIN INNER JOIN 消耗資源更多,所以如果您可以重新編寫(xiě)查詢以使得該查詢不使用任何 LEFT JOIN,則會(huì)得到非常可觀的回報(bào)(請(qǐng)參閱圖 1 中的圖)。

1 查詢

加快使用 LEFT JOIN 的查詢速度的一項(xiàng)技術(shù)涉及創(chuàng)建一個(gè) TABLE 數(shù)據(jù)類型,插入第一個(gè)表(LEFT JOIN 左側(cè)的表)中的所有行,然后使用第二個(gè)表中的值更新 TABLE 數(shù)據(jù)類型。此技術(shù)是一個(gè)兩步的過(guò)程,但與標(biāo)準(zhǔn)的 LEFT JOIN 相比,可以節(jié)省大量時(shí)間。一個(gè)很好的規(guī)則是嘗試各種不同的技術(shù)并記錄每種技術(shù)所需的時(shí)間,直到獲得用于您的應(yīng)用程序的執(zhí)行性能最佳的查詢。

測(cè)試查詢的速度時(shí),有必要多次運(yùn)行此查詢,然后取一個(gè)平均值。因?yàn)椴樵儯ɑ虼鎯?chǔ)過(guò)程)可能會(huì)存儲(chǔ)在 SQL Server 內(nèi)存中的過(guò)程緩存中,因此第一次嘗試耗費(fèi)的時(shí)間好像稍長(zhǎng)一些,而所有后續(xù)嘗試耗費(fèi)的時(shí)間都較短。另外,運(yùn)行您的查詢時(shí),可能正在針對(duì)相同的表運(yùn)行其他查詢。當(dāng)其他查詢鎖定和解鎖這些表時(shí),可能會(huì)導(dǎo)致您的查詢要排隊(duì)等待。例如,如果您進(jìn)行查詢時(shí)某人正在更新此表中的數(shù)據(jù),則在更新提交時(shí)您的查詢可能需要耗費(fèi)更長(zhǎng)時(shí)間來(lái)執(zhí)行。

避免使用 LEFT JOIN 時(shí)速度降低的最簡(jiǎn)單方法是盡可能多地圍繞它們?cè)O(shè)計(jì)數(shù)據(jù)庫(kù)。例如,假設(shè)某一產(chǎn)品可能具有類別也可能沒(méi)有類別。如果 Products 表存儲(chǔ)了其類別的 ID,而沒(méi)有用于某個(gè)特定產(chǎn)品的類別,則您可以在字段中存儲(chǔ) NULL 值。然后您必須執(zhí)行 LEFT JOIN 來(lái)獲取所有產(chǎn)品及其類別。您可以創(chuàng)建一個(gè)值為“No Category”的類別,從而指定外鍵關(guān)系不允許 NULL 值。通過(guò)執(zhí)行上述操作,現(xiàn)在您就可以使用 INNER JOIN 檢索所有產(chǎn)品及其類別了。雖然這看起來(lái)好像是一個(gè)帶有多余數(shù)據(jù)的變通方法,但可能是一個(gè)很有價(jià)值的技術(shù),因?yàn)樗梢韵?span lang="EN-US"> SQL 批處理語(yǔ)句中消耗資源較多的 LEFT JOIN。在數(shù)據(jù)庫(kù)中全部使用此概念可以為您節(jié)省大量的處理時(shí)間。請(qǐng)記住,對(duì)于您的用戶而言,即使幾秒鐘的時(shí)間也非常重要,因?yàn)楫?dāng)您有許多用戶正在訪問(wèn)同一個(gè)聯(lián)機(jī)數(shù)據(jù)庫(kù)應(yīng)用程序時(shí),這幾秒鐘實(shí)際上的意義會(huì)非常重大。

靈活使用笛卡爾乘積

對(duì)于此技巧,我將進(jìn)行非常詳細(xì)的介紹,并提倡在某些情況下使用笛卡爾乘積。出于某些原因,笛卡爾乘積 (CROSS JOIN) 遭到了很多譴責(zé),開(kāi)發(fā)人員通常會(huì)被警告根本就不要使用它們。在許多情況下,它們消耗的資源太多,從而無(wú)法高效使用。但是像 SQL 中的任何工具一樣,如果正確使用,它們也會(huì)很有價(jià)值。例如,如果您想運(yùn)行一個(gè)返回每月數(shù)據(jù)(即使某一特定月份客戶沒(méi)有定單也要返回)的查詢,您就可以很方便地使用笛卡爾乘積。 圖 2 中的 SQL 就執(zhí)行了上述操作。

雖然這看起來(lái)好像沒(méi)什么神奇的,但是請(qǐng)考慮一下,如果您從客戶到定單(這些定單按月份進(jìn)行分組并對(duì)銷售額進(jìn)行小計(jì))進(jìn)行了標(biāo)準(zhǔn)的 INNER JOIN,則只會(huì)獲得客戶有定單的月份。因此,對(duì)于客戶未訂購(gòu)任何產(chǎn)品的月份,您不會(huì)獲得 0 值。如果您想為每個(gè)客戶都繪制一個(gè)圖,以顯示每個(gè)月和該月銷售額,則可能希望此圖包括月銷售額為 0 的月份,以便直觀標(biāo)識(shí)出這些月份。如果使用 圖 2 中的 SQL,數(shù)據(jù)則會(huì)跳過(guò)銷售額為 0 美元的月份,因?yàn)樵诙▎伪碇袑?duì)于零銷售額不會(huì)包含任何行(假設(shè)您只存儲(chǔ)發(fā)生的事件)。

圖 3 中的代碼雖然較長(zhǎng),但是可以達(dá)到獲取所有銷售數(shù)據(jù)(甚至包括沒(méi)有銷售額的月份)的目標(biāo)。首先,它會(huì)提取去年所有月份的列表,然后將它們放入第一個(gè) TABLE 數(shù)據(jù)類型表 (@tblMonths) 中。下一步,此代碼會(huì)獲取在該時(shí)間段內(nèi)有銷售額的所有客戶公司的名稱列表,然后將它們放入另一個(gè) TABLE 數(shù)據(jù)類型表 (@tblCus-tomers) 中。這兩個(gè)表存儲(chǔ)了創(chuàng)建結(jié)果集所必需的所有基本數(shù)據(jù),但實(shí)際銷售數(shù)量除外。第一個(gè)表中列出了所有月份(12 行),第二個(gè)表中列出了這個(gè)時(shí)間段內(nèi)有銷售額的所有客戶(對(duì)于我是 81 個(gè))。并非每個(gè)客戶在過(guò)去 12 個(gè)月中的每個(gè)月都購(gòu)買(mǎi)了產(chǎn)品,所以,執(zhí)行 INNER JOIN LEFT JOIN 不會(huì)返回每個(gè)月的每個(gè)客戶。這些操作只會(huì)返回購(gòu)買(mǎi)產(chǎn)品的客戶和月份。

笛卡爾乘積則可以返回所有月份的所有客戶。笛卡爾乘積基本上是將第一個(gè)表與第二個(gè)表相乘,生成一個(gè)行集合,其中包含第一個(gè)表中的行數(shù)與第二個(gè)表中的行數(shù)相乘的結(jié)果。因此,笛卡爾乘積會(huì)向表 @tblFinal 返回 972 行。最后的步驟是使用此日期范圍內(nèi)每個(gè)客戶的月銷售額總計(jì)更新 @tblFinal 表,以及選擇最終的行集。

如果由于笛卡爾乘積占用的資源可能會(huì)很多,而不需要真正的笛卡爾乘積,則可以謹(jǐn)慎地使用 CROSS JOIN。例如,如果對(duì)產(chǎn)品和類別執(zhí)行了 CROSS JOIN,然后使用 WHERE 子句、DISTINCT GROUP BY 來(lái)篩選出大多數(shù)行,那么使用 INNER JOIN 會(huì)獲得同樣的結(jié)果,而且效率高得多。如果需要為所有的可能性都返回?cái)?shù)據(jù)(例如在您希望使用每月銷售日期填充一個(gè)圖表時(shí)),則笛卡爾乘積可能會(huì)非常有幫助。但是,您不應(yīng)該將它們用于其他用途,因?yàn)樵诖蠖鄶?shù)方案中 INNER JOIN 的效率要高得多。

拾遺補(bǔ)零

這里介紹其他一些可幫助提高 SQL 查詢效率的常用技術(shù)。假設(shè)您將按區(qū)域?qū)λ袖N售人員進(jìn)行分組并將他們的銷售額進(jìn)行小計(jì),但是您只想要那些數(shù)據(jù)庫(kù)中標(biāo)記為處于活動(dòng)狀態(tài)的銷售人員。您可以按區(qū)域?qū)︿N售人員分組,并使用 HAVING 子句消除那些未處于活動(dòng)狀態(tài)的銷售人員,也可以在 WHERE 子句中執(zhí)行此操作。在 WHERE 子句中執(zhí)行此操作會(huì)減少需要分組的行數(shù),所以比在 HAVING 子句中執(zhí)行此操作效率更高。HAVING 子句中基于行的條件的篩選會(huì)強(qiáng)制查詢對(duì)那些在 WHERE 子句中會(huì)被去除的數(shù)據(jù)進(jìn)行分組。

另一個(gè)提高效率的技巧是使用 DISTINCT 關(guān)鍵字查找數(shù)據(jù)行的單獨(dú)報(bào)表,來(lái)代替使用 GROUP BY 子句。在這種情況下,使用 DISTINCT 關(guān)鍵字的 SQL 效率更高。請(qǐng)?jiān)谛枰?jì)算聚合函數(shù)(SUMCOUNT、MAX 等)的情況下再使用 GROUP BY。另外,如果您的查詢總是自己返回一個(gè)唯一的行,則不要使用 DISTINCT 關(guān)鍵字。在這種情況下,DISTINCT 關(guān)鍵字只會(huì)增加系統(tǒng)開(kāi)銷。

您已經(jīng)看到了,有大量技術(shù)都可用于優(yōu)化查詢和實(shí)現(xiàn)特定的業(yè)務(wù)規(guī)則,技巧就是進(jìn)行一些嘗試,然后比較它們的性能。最重要的是要測(cè)試、測(cè)試、再測(cè)試。在此專欄的將來(lái)各期內(nèi)容中,我將繼續(xù)深入講述 SQL Server 概念,包括數(shù)據(jù)庫(kù)設(shè)計(jì)、好的索引實(shí)踐以及 SQL Server 安全范例。

如有向 Johnny 提出的問(wèn)題和建議,請(qǐng)發(fā)送電子郵件到 mmdata@microsoft.com


SQL高手篇:精妙SQL語(yǔ)句介紹

文章類別:SQL技巧 發(fā)表時(shí)間:2004-8-22 19:36:18瀏覽:522

http://www.net118.com/article/2004822193618.htm

 

說(shuō)明:復(fù)制表(只復(fù)制結(jié)構(gòu),源表名:a 新表名:b)

  SQL: select * into b from a where 1<>1   

  說(shuō)明:拷貝表(拷貝數(shù)據(jù),源表名:a 目標(biāo)表名:b)

  SQL: insert into b(a, b, c) select d,e,f from b;   

  說(shuō)明:顯示文章、提交人和最后回復(fù)時(shí)間

  SQL: select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b  

  說(shuō)明:外連接查詢(表名1a 表名2b)

  SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c   

  說(shuō)明:日程安排提前五分鐘提醒

  SQL: select * from 日程安排 where datediff('minute',f開(kāi)始時(shí)間,getdate())>5   

  說(shuō)明:兩張關(guān)聯(lián)表,刪除主表中已經(jīng)在副表中沒(méi)有的信息

  SQL:   delete from info where not exists ( select * from infobz where info.infid=infobz.infid )   

  說(shuō)明:--

  SQL:

  SELECT A.NUM, A.NAME, B.UPD_DATE, B.PREV_UPD_DATE FROM TABLE1,(SELECT X.NUM, X.UPD_DATE, Y.UPD_DATE PREV_UPD_DATE FROM (SELECT NUM, UPD_DATE, INBOUND_QTY, STOCK_ONHAND FROM TABLE2 WHERE TO_CHAR(UPD_DATE,'YYYY/MM') = TO_CHAR(SYSDATE, 'YYYY/MM')) X, (SELECT NUM, UPD_DATE, STOCK_ONHAND FROM TABLE2 WHERE TO_CHAR(UPD_DATE,'YYYY/MM') = TO_CHAR(TO_DATE(TO_CHAR(SYSDATE, 'YYYY/MM') &brvbar;&brvbar; '/01','YYYY/MM/DD') - 1, 'YYYY/MM') ) Y, WHERE X.NUM = Y.NUM +AND X.INBOUND_QTY + NVL(Y.STOCK_ONHAND,0) <> X.STOCK_ONHAND ) B WHERE A.NUM = B.NUM   

  說(shuō)明:--

  SQL:   select * from studentinfo where not exists(select * from student where studentinfo.id=student.id) and 系名稱='"&strdepartmentname&"' and 專業(yè)名稱='"&strprofessionname&"' order by 性別,生源地,高考總成績(jī)   
說(shuō)明: 從數(shù)據(jù)庫(kù)中去一年的各單位電話費(fèi)統(tǒng)計(jì)(電話費(fèi)定額賀電化肥清單兩個(gè)表來(lái)源)

  SQL:

  SELECT a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy') AS telyear, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '01', a.factration)) AS JAN, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '02', a.factration)) AS FRI, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '03', a.factration)) AS MAR, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '04', a.factration)) AS APR, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '05', a.factration)) AS MAY, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '06', a.factration)) AS JUE,SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '07', a.factration)) AS JUL, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '08', a.factration)) AS AGU, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '09', a.factration)) AS SEP, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '10', a.factration)) AS OCT, SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '11', a.factration)) AS NOV,SUM(decode(TO_CHAR(a.telfeedate, 'mm'), '12', a.factration)) AS DEC FROM (SELECT a.userper, a.tel, a.standfee, b.telfeedate, b.factration FROM TELFEESTAND a, TELFEE b WHERE a.tel = b.telfax) a GROUP BY a.userper, a.tel, a.standfee, TO_CHAR(a.telfeedate, 'yyyy')   

  說(shuō)明:四表聯(lián)查問(wèn)題:

  SQL: select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....   

  說(shuō)明:得到表中最小的未使用的ID號(hào)

  SQL:

  SELECT (CASE WHEN EXISTS(SELECT * FROM Handle b WHERE b.HandleID = 1) THEN MIN(HandleID) + 1 ELSE 1 END) as HandleID FROM Handle WHERE NOT HandleID IN (SELECT a.HandleID - 1 FROM Handle a)

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
SQL數(shù)字函數(shù)
標(biāo)準(zhǔn)SQL語(yǔ)法使用
SQL語(yǔ)句效率
存儲(chǔ)過(guò)程編寫(xiě)經(jīng)驗(yàn)和優(yōu)化措施
sqlserver數(shù)據(jù)庫(kù)操作大全
SQL的基本操作
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服