Microsoft Jet SQL for Access 2000

該系列的文章解釋了什麼是Microsoft? Jet SQL,並說明了它如何在Access 2000的應用程序中使用。本文是基礎、中級和高級三篇中的第二篇。這些文章循序漸進的說明了使用Jet SQL的語法和一些方法,並示範了對於Access 2000來說較新的Jet SQL的特徵。最後,本文的所有SQL參考都是針對Microsoft Jet 4.0 數據引擎所用的。

中級SQL說明
通過了解中級結構化查詢語言的一些概念,用戶可以增強控制數據庫的結構和對象的能力,並且可以通過許多有趣的和強有力的途徑操縱這些機構中包含的數據。結合使用諸如DAO和ADO之類的數據訪問方法,中級SQL 可以很大程度的提高用戶應用程序的靈活性及其表現。

基礎、中級和高級SQL的不同點
在基礎、中級和高級SQL之間劃分一條明顯的界限並不是一件容易的事情,在很多情況下,決定其所屬都只是簡單的決斷。但是對於該系列在Access 2000中使用SQL的文章來說,還考慮瞭如下的一些方面:

首先一點在於SQL語句本身的複雜級別。在前面的文章中,我們努力使用那些常用的語句,而且是最簡單的形式。本文則在前面基礎篇的基礎上介紹了更復雜的語句。
其次是在Access 2000中已經包含了一些新的SQL語句、子句和關鍵詞。儘管在本文中仍將使用Access上一版本中所包含的SQL語句,但是一定會出現一些在Access中第一次出現的SQL語句,在高級SQL一文中也是如此。
最後,那些關於安全性和多用戶解決方案的SQL語句將在高級篇中介紹,因爲這些語句常常是用於更復雜的應用程序中的
通過使用中級SQL,用戶可以爲你的Access應用程序增加更強的靈活性和能力。儘管簡單的和直接的SQL語句能夠完成很多的事情,但是使用更復雜的語句將擴展在數據庫中訪問和處理信息的方法範圍。使用中級SQL也將使得用戶可以更好的控制你的數據庫使用和維護工作

 

增強SQL
在Access 2000中,爲了支持Access的新特性,爲了和ANSI-92的標準更加一致,並且允許在Access 和 Microsoft? SQL Server?間的更好的兼容性,包含在Microsoft Jet 4.0數據引擎中的SQL作了許多增強。Jet數據引擎現在有兩種格式的SQL語法:一種是支持以前使用的SQL語法,另一種是支持新的SQL語法規範。需要格外注意的是,只有在用戶使用ActiveX? Data Objects (ADO)和Jet OLE DB provider時新的語法纔是可用的,而當前通過Access SQL View接口或者DAO是無法使用新的語法的。本文指出只有通過Jet OLE DB provider 和 ADO才能夠使用某個特定的SQL命令。

在Access的上一版本中,數據訪問對象(DAO)是主要的數據訪問方法。而現在發生了改變,儘管DAO 仍舊被支持,但新的數據訪問方法是使用ADO。ADO是微軟的通用數據訪問戰略(Microsoft's Universal Data Access strategy)的一部分,其最基本的假設是無論數據存在那裏都是可以訪問的,不管是數據庫、目錄結構還是某重用戶自定義的數據庫。

在討論Microsoft Jet SQL 時,ADO是非常重要的,正如在前面提到的,一些新的SQL語句只有在使用ADO 和Jet OLE DB provider時纔是可用的。在本文和與本文相配套的示範數據庫中,所有的代碼都是使用ADO些的。那些沒有特意指明爲只有通過ADO纔可用的SQL語句都可以通過Access SQL View 用戶接口或 DAO來執行。詳盡的關於ADO的討論超出了本文的範圍,用戶可以在下面的網站中找到最近的信息
http://www.microsoft.com/data/ado/.

 

SQL代碼規範
本文使用一致性的SQL代碼規範。與所有的代碼規範相同,目的是使用易讀和易於理解的方式來顯示代碼。這就要通過空格、換行和大寫關鍵字的結合使用來實現。通常來說,要使用大寫字母來打印SQL的關鍵字,如果SQL語句必須換行,儘量使SQL語句的主要部分一起換行。看過一些例子之後,相信讀者會對此有較好的感覺。

不合格式的SQL代碼
CREATE TABLE tblCustomers (CustomerID INTEGER NOT NULL, [Last Name] TEXT(50) NOT NULL, [First Name] TEXT(50) NOT NULL, Phone TEXT(10), Email TEXT(50))

良好格式的SQL代碼

CREATE TABLE tblCustomers (
...CustomerID INTEGER NOT NULL,
...[Last Name] TEXT(5) NOT NULL,
...[First Name] TEXT(50) NOT NULL,
...Phone TEXT(10),
...Email TEXT(50))
改變數據表
在建立或倒入一個數據表之後,用戶可能需要修改表的設計。這時就可以使用ALTER TABLE語句。但是注意,改變現存的表的結構可能會導致用戶丟失一些數據。比如,改變一個域的數據類型將導致數據丟失或舍入錯誤,這取決於用戶現在使用的數據類型。改變數據表也可能會破壞用戶的應用程序中涉及到所改變的域的部分。所以用戶在修改現有表的結構之前一定要格外小心。

使用ALTER TABLE 語句,用戶可以增加,刪除或改變列或域,也可以增加或刪除一個約束。還可以爲某個域設定缺省值,但是一次只能修改一個域。假設我們有一個記賬單的數據庫,而我們想在顧客數據表中增加一個域,這時可以使用ALTER TABLE 語句,在其ADD COLUMN 子句後寫上域的名稱、數據類型和數據的大小(如果需要的話)。

ALTER TABLE tblCustomers
ADD COLUMN Address TEXT(30)
要改變域的數據類型或大小,可以使用ALTER COLUMN子句,在後面加上期望的數據類型和數據的大小。

ALTER TABLE tblCustomers
ALTER COLUMN Address TEXT(40)
如果需要改變域的名稱,則必須刪除該域並重新創建。刪除一個域要使用DROP COLUMN 子句,在其後跟上域的名稱。

ALTER TABLE tblCustomers
DROP COLUMN Address
注意使用這種方法將會刪除該域的現存數據。如果需要保存這些數據,則用戶需要在Access的用戶界面的設計模式中改變該域的名稱,或者編寫代碼將現存的數據保存在一個臨時的表中然後將其添加到改名後的表中。

缺省值是指在表中增加新紀錄並且沒有爲該列賦值時自動填充到該域中的值。爲某域設置缺省值,要在定義域的類型後使用使用DEFAULT關鍵字,不管是使用ADD COLUMN或 ALTER COLUMN 子句。

ALTER TABLE tblCustomers
ALTER COLUMN Address TEXT(40) DEFAULT Unknown
注意缺省值並不使用單引號包含,如果用了單引號,則引號也會插入到記錄中。在CREATE TABLE語句中也可以使用DEFAULT關鍵字。

CREATE TABLE tblCustomers (
CustomerID INTEGER CONSTRAINT PK_tblCustomers
PRIMARY KEY,
[Last Name] TEXT(50) NOT NULL,
[First Name] TEXT(50) NOT NULL,
Phone TEXT(10),
Email TEXT(50),
Address TEXT(40) DEFAULT Unknown)


注意: DEFAULT 語句只有在Jet OLE DB provider和ADO中可以執行,在Access SQL View的用戶界面中使用將會返回錯誤信息。

下面的部分將討論如何在ALTER TABLE語句中使用約束。要獲得更詳細的有關ALTER TABLE的說明,請在Office 助手中或在Microsoft Access 幫助的回答嚮導的標籤頁中輸入ALTER TABLE ,然後單擊查找。

約束
在《Access 2000的基礎Microsoft Jet SQL》一文中,我們討論了建立表之間的聯繫的約束方法。約束也能用於建立主鍵和參考完整性,來限制插入到一個域中的數據值。通常,約束可以用於保持用戶數據庫中的數據完整性和一致性。

共有兩種類型的約束:單數據域(或稱域級的)的約束和多數據域(或稱表級的)的約束。兩種約束都可以用在CREATE TABLE 或 ALTER TABLE 語句中。

單域的約束,也就是通常所說的列級的約束,是在域及其數據類型定義後針對該域定義的。下面我們使用用戶表,在CustomerID域生成一個單域的主鍵。增加約束時,在域名後使用CONSTRAINT關鍵字。

ALTER TABLE tblCustomers
ALTER COLUMN CustomerID INTEGER
CONSTRAINT PK_tblCustomers PRIMARY KEY


注意這裏給出了約束的名稱。用戶還可以在定義主鍵時使用簡稱而省略CONSTRAINT子句。

ALTER TABLE tblCustomers
ALTER COLUMN CustomerID INTEGER PRIMARY KEY


然而,使用簡稱的方法將導致Access隨機的生成約束的名稱,從而使得在代碼中難以引用。所以,最好給約束制定名稱。

要刪除一個約束,可以在ALTER TABLE 語句中使用DROP CONSTRAINT 子句,並給出約束的名稱。

ALTER TABLE tblCustomers
DROP CONSTRAINT PK_tblCustomers


約束還可以用來給域限制允許值。用戶可以將限制值設爲非空(NOT NULL)或唯一( UNIQUE),或者定義一個檢驗性的約束,該約束指一種可以應用於某個域的規則。比如用戶希望限制姓和名的域是唯一的,就意味着在表中永遠不會有兩個相同姓名的記錄存在。這是因爲這種約束是多域的性的,是在表的級別定義的,而非域的級別。使用ADD CONSTRAINT子句可以定義一個多域的列表。

ALTER TABLE tblCustomers
ADD CONSTRAINT CustomerNames UNIQUE
([Last Name], [First Name])


注意: 我們在這裏只是示範一下如何使用約束,而在實際的應用程序中,用戶可能並不希望徹底限制姓名的唯一性。

檢驗性約束是一種新的強有力的SQL特性,它通過一個表達式從而允許用戶在表中添加數據合法性檢驗,該表達式可以指向一個單域,也可以指向跨越一個或多個表的多個域。比如用戶希望確定輸入到發票記錄中的數值是否總是大於0,則可以在ALTER TABLE語句的ADD CONSTRAINT子句中定義一個CHECK關鍵字。

ALTER TABLE tblInvoices
ADD CONSTRAINT CheckAmount
CHECK (Amount > 0)


注意: 檢驗性約束語句只能通過Jet OLE DB provider和ADO來執行,在Access SQL View的用戶界面中使用將返回錯誤信息。而且,要刪除一個檢驗性約束,也必須在Jet OLE DB provider 和ADO中執行DROP CONSTRAINT語句。另外,如果用戶已經定義了一個檢驗性約束: (1) 在Access的用戶界面中並不會顯示爲一個合法性規則,(2) 用戶也不能在該界面中定義合法性文本的屬性,否則將給出一般性錯誤信息,(3) 在用戶通過ADO使用DROP CONSTRAINT語句之前,不能夠通過Access的用戶界面或者在代碼中刪除數據表。

用來定義一個檢驗性約束的表達式也可以用來指向同一個表中的多個域,甚至是其他表中的域。其中可以使用任何在Microsoft Jet SQL 中合法的操作符,比如SELECT 語句、數學運算符、以及集合函數等。用來定義檢驗性約束的表達式的長度不能超過64個字符。

設想用戶希望在將顧客加入到Customers 表之前檢查每個顧客的信用額度。則可以使用帶有ADD COLUMN 和CONSTRAINT 子句的ALTER TABLE 語句生成一個約束,該約束將查找在CreditLimit表中的值來驗證顧客的信用額度。下面的SQL語句將生成一個tblCreditLimit 表,然後將CustomerLimit域加入到tblCustomers 表中,並將檢驗性約束加到tblCustomers表,最後對該檢驗性約束進行測試。

CREATE TABLE tblCreditLimit (
Limit DOUBLE)
INSERT INTO tblCreditLimit
VALUES (100)
ALTER TABLE tblCustomers
ADD COLUMN CustomerLimit DOUBLE
ALTER TABLE tblCustomers
ADD CONSTRAINT LimitRule
CHECK (CustomerLimit <= (SELECT Limit
FROM tblCreditLimit))
UPDATE TABLE tblCustomers
SET CustomerLimit = 200
WHERE CustomerID = 1


注意:當用戶執行UPDATE TABLE語句時,將被提示更新失敗,因爲該語句違反了檢驗性約束。如果用戶使用小於等於100的值來更新CustomerLimit域,就能夠成功。

約束-II
級聯性更新和刪除
約束還可以用來在數據庫中的表間建立參考完整性。具有參考完整性意味着數據是一致的和未被破壞的。比如,如果刪除了一個顧客的記錄但是該顧客的運單記錄仍舊存在數據庫中,這時數據就是非一致的,即指數據庫中存在着一個孤立的顧客運單記錄。參考完整性是在用戶建立各個表間的關係時建立的。除了建立參考完整性之外,用戶還可以使用級聯性更新和刪除來確保相互參考的表保持同步。例如,一旦定義了級聯性更新和刪除,當用戶刪除顧客記錄時,該顧客的運單記錄也將自動刪除。

要使用級聯性更新和刪除,用戶可以在ALTER TABLE 語句的CONSTRAINT子句中使用ON UPDATE CASCADE 和/或 ON DELETE CASCADE 關鍵字。注意他們都必須是應用於外鍵的。

ALTER TABLE tblShipping
ADD CONSTRAINT FK_tblShipping
FOREIGN KEY (CustomerID) REFERENCES
tblCustomers (CustomerID)
ON UPDATE CASCADE
ON DELETE CASCADE


外鍵
在處理外鍵時,有關快速外鍵(fast foreign key)的概念是很有用的。快速外鍵即是一種沒有索引的外鍵。儘管這乍聽起來有點不合理,但卻可以得到很好的解釋。在缺省情況下,一旦定義了一個外鍵,將會自動生成一個基於該外鍵中列的索引,這在很多情況下提高了執行保持參考完整性的操作的表現。然而,如果在定義外鍵的域中存在許多重複值,外鍵索引將會影響增加和刪除數據使得效率。要防止基於外鍵的索引的生成,我們可以在定義外鍵是NO INDEX關鍵字。

ALTER TABLE tblInvoices
ADD CONSTRAINT FK_tblInvoices
FOREIGN KEY NO INDEX (CustomerID) REFERENCES
tblCustomers (CustomerID)
ON UPDATE CASCADE
ON DELETE CASCADE


注意: 快速外鍵語句只能通過Jet OLE DB provider 和 ADO來執行。在Access SQL View的用戶界面中使用將返回錯誤信息。而且,要刪除一個快速外鍵,也必須在Jet OLE DB provider 和ADO中執行DROP CONSTRAINT語句。

在記錄按序排列的數據庫應用中,快速外鍵也將發揮作用。比如這裏有一個用來辨別所跟蹤的顧客類型的 CustomerTypes的表,一個Customer 表和一個Orders 表。在CustomerTypes表中有10行,在 Customer 表中有100000行,在Orders表中有350000行。這時採用在Customers 表中指向CustomerTypes表中的主鍵的快速外鍵將是很好的選擇,因爲在100000行記錄外最多隻有10行唯一的記錄。這時索引對於提取數據毫無用處,並且在CustomerType中插入、刪除和更新數據是成爲累贅。

而另一方面,快速外鍵應用於Orders 表中的CustomerID 列很可能是沒有用處的,因爲那些值每一個都代表了不同的客戶,所以一般是唯一的。在這種情況下,使用通常的帶有索引的外鍵將會很有裨益,這是因爲它是應用在連結和其他查找規則上的。

注意: 儘管在本節的大部分例子中使用的是ALTER TABLE語句,但是所有這些都是可以寫在CREATE TABLE 語句中的。

要了解有關CONSTRAINT子句的更多信息,請在Office 助手中或在Microsoft Access 幫助的回答嚮導的標籤頁中輸入ALTER TABLE ,然後單擊查找。

 

 

 


數據類型
在努力使基Jet數據引擎的Access應用程序易於向那些基於Microsoft SQL Server 或 MSDE的應用轉化方面,Jet 數據引擎改變了一些數據類型,增加了一些新的數據類型字。下面的部分將討論主要的數據類型及其如何實現的。

文本(TEXT)數據類型
文本(TEXT)數據類型是用來設置一個可以存儲純文本的域的,也可以用來存儲同時包含文本和數字的內容,但其中的數字並不是用於計算的,比如電話號碼或者電子郵件地址。當用戶通過ACESS的用戶界面創建表時,用戶有兩種基本的文本類型:文本(TEXT)和備註(MEMO)。但是通過SQL語句如CREATE TABLE或者 ALTER TABLE 來創建表時,則還有其他許多的TEXT 和 MEMO類型的同義字可供選擇。

總的來說,文本域最多可以有255個字符,而備註域則最多可以有65,535 個字符,但是如果備註域不包含任何二進制數據的話,其唯一的限制就是整個數據庫的最大容量(大概是2.14GB 或 1,070,000,000 雙字節字符)。另外,沒有用到的文本與部分並不會保存在內存中。

下面的表格列示了最基本的Jet 文本數據類型,它的同義字以及所分配的字節數。

Jet 數據類型
同義字
存儲容量

TEXT(文本)
TEXT, TEXT(n), CHAR, CHAR(n), ALPHANUMERIC, ALPHANUMERIC(n), STRING, STRING(n), VARCHAR, VARCHAR(n), NTEXT(n), NCHAR, NCHAR(n), CHAR VARYING, CHAR VARYING(n), CHARACTER VARYING, CHARACTER VARYING(n), NATIONAL CHAR, NATIONAL CHAR(n), NATIONAL CHARACTER, NATIONAL CHARACTER(n), NATIONAL CHAR VARYING, NATIONAL CHAR VARYING(n), NATIONAL CHARACTER VARYING, NATIONAL CHARACTER VARYING(n)
最多可以有255個字符,每個字符兩個子節(如果不進行壓縮)。

MEMO(備註)
LONGTEXT, LONGCHAR, 注意, NTEXT
65,535 個字符;如果非二進制數據可以有2.14 GB


下面的CREATE TABLE語句示範了可以用來通過Access SQL View用戶界面創建表的TEXT 和MEMO的不同形式的同義詞。

CREATE TABLE tblUITextDataTypes (
Field1_TEXT TEXT,
Field2_TEXT25 TEXT(25),
Field3_MEMO MEMO,
Field4_CHAR CHAR,
Field5_CHAR25 CHAR(25),
Field6_LONGTEXT LONGTEXT,
Field7_LONGCHAR LONGCHAR,
Field8_ALPHA ALPHANUMERIC,
Field9_ALPHA25 ALPHANUMERIC(25),
Field10_STRING STRING,
Field11_STRING25 STRING(25),
Field12_VARCHAR VARCHAR,
Field13_VARCHAR25 VARCHAR(25),
Field14_NOTE NOTE)


如果用戶通過Access的用戶界面察看上面的tblUITextDataTypes表的設計的話,將會看到MEMO、 LONGTEXT、 LONGCHAR、和注意同義字都是MEMO 的數據類型,其他的所有同義字都是TEXT數據類型。對於那些沒有定義長度的TEXT 數據類型,缺省的長度爲255個字符。

雖說上面的SQL語句也可以通過Jet OLE DB provider和 ADO來執行,但還是有一些其他的TEXT 和MEMO 數據類型的不同定義只能通過Jet OLE DB provider 和ADO來執行。

CREATE TABLE tblCodeTextDataTypes
Field1_NTEXT NTEXT,
Field2_NTEXT25 NTEXT(25),
Field3_NCHAR NCHAR,
Field4_NCHAR NCHAR(25),
Field5_VARYING CHAR VARYING,
Field6_VARYING CHAR VARYING(25),
Field7_VARYING CHARACTER VARYING,
Field8_VARYING CHARACTER VARYING(25),
Field9_NATIONAL NATIONAL CHAR,
Field10_NATIONAL NATIONAL CHAR(25),
Field11_NATIONAL NATIONAL CHARACTER,
Field12_NATIONAL NATIONAL CHARACTER(25),
Field13_NATIONAL NATIONAL CHAR VARYING,
Field14_NATIONAL NATIONAL CHAR VARYING(25),
Field15_NATIONAL NATIONAL CHARACTER VARYING,
Field16_NATIONAL NATIONAL CHARACTER VARYING(25))


如果用戶通過Access的用戶界面察看上面的tblUITextDataTypes表的設計的話,將會看到只有NCHAR數據類型是MEMO,其他的都是TEXT數據類型。對於那些沒有定義長度的TEXT 數據類型,缺省的長度爲255個字符。

注意: 在上面的SQL語句中列示的這些數據類型只能通過Jet OLE DB provider 和ADO來執行,在Access SQL View的用戶界面中使用將導致錯誤信息。還要注意如果通過Jet OLE DB provider和 ADO創建了一個TEXT數據類型的域,則通過Access用戶界面看到的將是MEMO的數據類型。

Unicode壓縮

現在在Microsoft Jet 4.0 數據引擎中,所有的TEXT數據類型都是以兩個字節的統一編碼形式存儲的。它取代了前面版本中採用的多字節字符集(Multi-byte Character Set ,MBCS)格式。雖然雙字節的格式需要更多的空間來存儲每個字符,但可以定義使用TEXT數據類型的自動進行壓縮。

在用戶使用SQL建立的TEXT的數據類型時,雙字節編碼的壓縮屬性缺省設置爲NO,如果需要將該屬性設置爲Yes,用戶可以在定義域的時候使用WITHCOMPRESSION (或者 WITH COMP)關鍵字。

下面的CREATE TABLE 語句將創建一個新的顧客表,這裏將雙字節編碼的壓縮屬性設置爲Yes。

CREATE TABLE tblCompressedCustomers (
CustomerID INTEGER CONSTRAINT
PK_tblCompCustomers PRIMARY KEY,
[Last Name] TEXT(50) WITH COMP NOT NULL,
[First Name] TEXT(50) WITH COMPRESSION NOT NULL,
Phone TEXT(10),
Email TEXT(50),
Address TEXT(40) DEFAULT Unknown)

 


注意WITH COMPRESSION 和WITH COMP關鍵字要在NOT NULL之前定義。用戶也可以使用ALTER TABLE語句改變現存域的雙字節編碼的壓縮屬性,如下所示:

ALTER TABLE tblCustomers
ALTER COLUMN [Last Name] TEXT(50) WITH COMPRESSION


注意: 在上面的SQL語句中列示的WITH COMPRESSION and WITH COMP關鍵字只能通過Jet OLE DB provider 和ADO來執行,在Access SQL View的用戶界面中使用將導致錯誤信息。

在用戶設計數據表時採取那種數據類型取決於用戶的應用程序的目的。如果該應用程序總是應用在Jet數據庫的基礎上,則應該使用最適宜的那些數據類型。但如果該應用程序最終要用到ODBC-compliant的數據庫上,比如SQL Server 或 MSDE,則要使用那些是一致最方便的數據類型。

 

數字( NUMERIC)數據類型
數字(NUMERIC)數據類型是用來定義存儲計算用數字的域的。通常,將某種NUMERIC類型與其他的區別開來的是用來存儲數據的字節數,它也影響着所存儲數字的精度。許多Jet SQL 的數據類型豆油協同義字可以用來進行定義,到底使用哪一個取決於該數據表是僅在某個Jet數據庫中還是將移植到諸如Microsoft SQL Server的數據庫服務器中。如果將進行移植,用戶應選擇那些使得移植最容易進行的數據類型。

下面的表格列示了基本的Jet NUMERIC數據類型,它的各種同義字以及爲期分配的字節數。

Jet 數據類型
同義字
存儲大小

TINYINT
INTEGER1, BYTE
1 byte

SMALLINT
SHORT, INTEGER2
2 bytes

INTEGER
LONG, INT, INTEGER4
4 bytes

REAL
SINGLE, FLOAT4, IEEESINGLE
4 bytes

FLOAT
DOUBLE, FLOAT8, IEEEDOUBLE, NUMBER
8 bytes

DECIMAL
NUMERIC, DEC
17 bytes


下面的CREATE TABLE 語句示範了各種可以在通過Access SQL View 的用戶界面創建表時使用的SNUMERIC 數據類型。

CREATE TABLE tblUINumericDataTypes (
Field1_INT INT,
Field2_INTEGER INTEGER,
Field3_LONG LONG,
Field4_INTEGER1 INTEGER1,
Field5_BYTE BYTE,
Field6_NUMERIC NUMERIC,
Field7_REAL REAL,
Field8_SINGLE SINGLE,
Field9_FLOAT FLOAT,
Field10_FLOAT4 FLOAT4,
Field11_FLOAT8 FLOAT8,
Field12_DOUBLE DOUBLE,
Field13_IEEESINGLE IEEESINGLE,
Field14_IEEEDOUBLE IEEEDOUBLE,
Field15_NUMBER NUMBER,
Field16_SMALLINT SMALLINT,
Field17_SHORT SHORT,
Field18_INTEGER2 INTEGER2,
Field19_INTEGER4 INTEGER4)


雖然上面的SQL 語句也可以通過Jet OLE DB provider 和ADO來執行,仍有一些其他的NUMERIC 數據類型的形式只能通過Jet OLE DB provider 和 ADO來執行。

CREATE TABLE tblCodeNumericDataTypes (
Field1_TINYINT TINYINT,
Field2_DECIMAL DECIMAL,
Field3_DEC DECIMAL,
Field4_DPRECISION DOUBLE PRECISION)


注意: 上面的SQL 語句中的數據類型只能通過Jet OLE DB provider 和 ADO來執行,在Access SQL View的用戶界面中使用將導致錯誤信息。還要注意如果通過Access SQL View 建立了一個NUMERIC 數據類型的域,通過Access 用戶界面察看錶的設計時看到的將是DOUBLE 數據類型,但是如果通過Jet OLE DB provider 和 ADO建立NUMERIC數據類型,通過Access 用戶界面看到的將是DECIMAL數據類型.

使用新的DECIMAL 數據類型,用戶可以設定數值的精度和小數位。精度就是該域所能包含的數字的總數,而小數位則決定了小數點右面能有幾位數字,精度缺省值是18,最大的允許值28,而小數位缺省的是0,最大值時28。

CREATE TABLE tblDecimalDataTypes (
DefaultType DECIMAL,
SpecificType DECIMAL(10,5))


貨幣(CURRENCY)數據類型
貨幣(CURRENCY)數據類型是用來存儲15位整數和4位小數的數字值的,它使用8個字節的存儲量,其唯一的同義字是MONEY。

下面的CREATE TABLE 語句示範了CURRENCY 數據類型在創建數據表時的用法,它既可以在Access SQL View 用戶界面中也可以在Jet OLE DB provider 和 ADO中使用。

CREATE TABLE tblCurrencyDataTypes (
Field1_CURRENCY CURRENCY,
Field2_MONEY MONEY)


是否(BOOLEAN )數據類型

是否(BOOLEAN)是邏輯數據類型,其值爲是(TRUE)或否(FALSE)。它們使用一個字節的存儲量,同義字有BIT、 LOGICAL、 LOGICAL1 和 YESNO。 True的值等於–1, False的值等於0。

下面的CREATE TABLE 語句示範了通過Jet OLE DB provider 和 ADO 來創建BOOLEAN 數據類型的不同形式。

CREATE TABLE tblUIBooleandataTypes (
Field1_BIT BIT,
Field2_LOGICAL LOGICAL,
Field3_LOGICAL1 LOGICAL1,
Field4_YESNO YESNO)


字節(BINARY )數據類型

字節(BINARY )數據類型以二進制的本來面目存儲小容量的任何類型的數據。它對於所存儲的每個字符只使用1個字節的存儲量,用戶可以指定所分配的字節數。如果沒有制定字節數,缺省的值是510,這也是所能允許的最大字節數。它的同義字有BINARY、 VARBINARY和 BINARY VARYING。BINARY 數據類型在Access 用戶界面中是不可用的。

下面的 CREATE TABLE 語句示範了可以用來在Access SQL View 用戶界面中使用的BINARY 數據類型的不同形式。

CREATE TABLE tblUIBinaryDataTypes (
Field1_BINARY BINARY,
Field2_BINARY250 BINARY(250),
Field3_VARBINARY VARBINARY,
Field4_VARBINARY250 VARBINARY(250))


雖然上面的SQL語句也可以通過Jet OLE DB provider 和 ADO執行,但仍然有些其他的binary 數據類型的同義字只能通過Jet OLE DB provider 和 ADO來執行,如下所示:

CREATE TABLE tblCodeBinaryDataTypes (
Field1_BVARYING BINARY VARYING,
Field2_BVARYING250 BINARY VARYING(250))

OLEOBJECT 數據類型
OLEOBJECT 數據類型用來存儲大的二進制對象,比如Word文檔或者Excel表單。它的字節數並不確定,最大可達2.14 GB。其同義字有:IMAGE、LONGBINARY、GENERAL 和 OLEOBJECT

下面的 CREATE TABLE 語句展示了通過Access SQL View 用戶界面或Jet OLE DB provider和ADO 來創建表時使用OLEOBJECT 數據類型。

CREATE TABLE tblImageDataTypes (
Field1_IMAGE IMAGE,
Field2_LONGBINARY LONGBINARY,
Field3_GENERAL GENERAL,
Field4_OLEOBJECT OLEOBJECT)


日期時間(DATETIME)數據類型

日期時間(DATETIME)數據類型用來存儲日期、時間以及日期和時間的結合值,年數可以從100到 9999。它使用8個字節的存儲量,其同義字有DATE、TIME、DATETIME和 TIMESTAMP

下面的 CREATE TABLE 語句展示了通過Access SQL View 用戶界面或Jet OLE DB provider 和 ADO 創建表示所使用的DATETIME 數據類型的不同形式。

CREATE TABLE tblDateTimeDataTypes (
Field1_DATE DATE,
Field2_TIME TIME,
Field3_DATETIME DATETIME,
Field4_TIMESTAMP TIMESTAMP)


COUNTER 數據類型

COUNTER 數據類型用來存儲長整型數值,該數值在表中每增加一條新的紀錄時能夠自動增加。使用COUNTER 數據類型,用戶可以設定一個種子值和增加值,種子值是當第一個記錄插入到表中時將輸入到域中的數值,而增加值用來加到上一個記數值上作爲下一個記數值。如果沒有指定種子值和增加值,它們都將缺省的使用1。在一個表中只能有一個COUNTER域。其同義字有 COUNTER、AUTOINCREMENT和IDENTITY。

下面的 CREATE TABLE 語句展示了通過Access SQL View 用戶界面創建表時使用的COUNTER 數據類型的同義字。

CREATE TABLE tblUICounterDataTypes (
Field1 COUNTER,
Field2 TEXT(10))


注意這裏沒有指定種子值和增加值,所有都將採用缺省值1。定義COUNTER 數據類型的另一種方式是使用AUTOINCREMENT 關鍵字,如下所示:

CREATE TABLE tblUICounterDataTypes (
Field1 AUTOINCREMENT(10,5),
Field2 TEXT(10))


這一次種子值和增加值都指定了,則開始值時10,每次將加5。上面的SQL 語句也可以通過Jet OLE DB provider 和 ADO執行,另外還有counter 數據類型的另一種形式,只能通過Jet OLE DB provider 和 ADO來執行,即IDENTITY 關鍵字,它和SQL Server的 IDENTITY 數據類型是相兼容的。

CREATE TABLE tblCodeCounterDataTypes
Field1_IDENTITY IDENTITY(10,5),
Field2 TEXT(10))


這裏的種子值和增加值都可以通過ALTER TABLE 語句進行修改,修改後所有新插入的行將使用新的值。但是, COUNTER 數據類型常常都是用於主鍵的,而主鍵要求每列唯一。如果你改變了種子值, 將可能導致主鍵域的重複值,從而發生錯誤。

ALTER TABLE tblUICounterDataTypes
ALTER COLUMN Field1 COUNTER(10,10)
注意: 如果某個現存的列已經包含了數據的話,用戶不能使用ALTER TABLE 語句來將該列的數據類型改變爲COUNTER 數據類型。

在以前版本的Jet數據庫中,壓縮數據庫之後,種子值將被置爲可能的最大值。在Jet 4.0中仍然如此,只要種子值和增加值的採用的是缺省值1的話。如果用戶指定了不等於缺省值的種子值和增加值,在壓縮數據庫是並不會重置種子值。

@@IDENTITY 變量

@@IDENTITY 變量是一個全局的SQL變量,用戶可以用它來提取使用COUNTER數據類型的列的最後使用值。用戶在提取@@IDENTITY 變量時,不能指定表的名稱。返回值總是最近的通過代碼插入了數據的表的COUNTER域。

SELECT @@IDENTITY
要給@@IDENTITY 值加上某個值,要將該變量用方括號括起來。

SELECT [@@IDENTITY] + 1
注意 上面SQL 語句中的@@IDENTITY變量只能通過Jet OLE DB provider 和 ADO執行提取,通過Access SQL View 用戶界面提取的值將是0,另外,該值只有在通過代碼插入記錄時纔會改變,如果通過用戶接口,不管是數據表單、窗體還是Access SQL View窗口中的SQL語句, @@IDENTITY返回值都是0。因此, @@IDENTITY 的值只有在剛剛通過代碼加入了記錄是纔是準確的。

要獲得更詳細的有關數據類型的說明,請在Office 助手中或在Microsoft Access 幫助的回答嚮導的標籤頁中輸入ALTER TABLE ,然後單擊查找。

 

《基礎Microsoft Jet SQL for Access 2000》一文告訴我們如何使用SQL來檢索和管理存儲在數據庫中的信息。本文的後面部分將討論中級數據操縱語言(DML)語句,這將使得用戶可以更好的控制信息檢索和處理的方式。

謂詞
謂詞指限定一個SELECT 語句的子句,同WHERE 子句類似,但是謂詞是在書寫列的列表之前定義的。謂詞還可以進一步的限制用戶所提取的記錄集,在某些情況下,過濾出任何可能存在的重複值。

ALL關鍵字
在SQL語句中,如果沒有定義任何謂詞的話,將使用缺省的ALL關鍵字。它意味着所有的符合SQL語句所設定的條件的記錄都將被提取出來。回到我們的發票數據庫中,從顧客表中提取所域的記錄如下:

SELECT *
FROM tblCustomers


注意儘管這裏ALL關鍵詞並沒有定義,但它是缺省值。我們也可以如下書寫該語句:

SELECT ALL *
FROM tblCustomers


DISTINCT關鍵字

DISTINCT關鍵字用來控制結果集中重複的值如何進行處理,那些對於指定的列來說用戶相同值的行將被過濾掉。如果多於指定的列大於一,則所有指定的列的結合將作爲過濾條件。例如,如果用戶查詢Customers表中姓氏不同的記錄,則返回的值都將是唯一的,任何重複姓氏的名字都將以結果集中的一個記錄作爲其結果。

SELECT DISTINCT [Last Name]
FROM tblCustomers


尤其要注意的是,使用DISTINCT關鍵字的查詢所返回的結果集不能更新,即是隻讀的。

DISTINCTROW 關鍵字
DISTINCTROW 關鍵字和DISTINCT關鍵字類似,但前者是基於整行而非個別的域的。他只有在處理多個表時,並且只有在用戶從某幾個但非全部的表中選擇數據域時纔是有用的。如果用戶的查詢是基於一個表的,或者要從所有的表中選擇數據域,則DISTINCTROW 關鍵字本質上和ALL關鍵字相同。

例如,在我們的發票數據庫中,每個顧客都可能沒有、有一個或多個發票記錄。假設我們希望找出有多少擁有多於一張發票的顧客,這時可以使用DISTINCTROW關鍵字來進行選擇。

SELECT DISTINCTROW [Last Name], [First Name]
FROM tblCustomers INNER JOIN tblInvoices
ON tblCustomers.CustomerID = tblInvoices.CustomerID


如果我們不使用DISTINCTROW 關鍵字,得到的將是每個顧客的所有發票記錄的行。(這裏的 INNER JOIN 語句將在後面的部分講解)。

TOP關鍵字
TOP關鍵字用來返回通過ORDER BY子句所指定的數據行中頂部或底部的某些行。ORDER BY 子句用來指定這些數據列是用升序還是降序排列。如果存在相等值,則TOP關鍵字將返回所有值相等的行。比如我們希望確定我們的發票數據庫中最高額的三條發票記錄,可以如下書寫SQL語句:

SELECT TOP 3 InvoiceDate, Amount
FROM tblInvoices
ORDER BY Amount DESC


我們也可以將PERCENT關鍵字和TOP關鍵字同時使用,來返回由ORDER BY子句所指定的數據行中頂部或底部的一定比例的行,如下所示:

SELECT TOP 25 PERCENT InvoiceDate, Amount
FROM tblInvoices
ORDER BY Amount DESC


注意如果用戶沒有定義ORDER BY 子句,則TOP關鍵字將毫無意義,返回的是隨機採樣的一些行。

要了解有關謂詞的更多信息,請在Office 助手中或在Microsoft Access 幫助的回答嚮導的標籤頁中輸入ALL、DISTINCT等謂詞,然後單擊查找。

SQL 表達式
一個SQL表達式就是作爲SQL語句的一部分的一個字符串,並可以得到一個值。你可以任意組合運算符、常數、文字值、函數、域名、控制和屬性來建立你的SQL表達式。而" Microsoft Jet SQL for Access 2000高級版"一文就向你描述瞭如何在WHERE子句中使用表達式來限制SQL語句;而且在本文隨後的部分,我們將學習各種能夠用於表達式的SQL操作符。

IN操作
IN操作是用來判斷一個表達式的值是否屬於一個指定列表中的值。如果這個表達式等於列表中的一個值,IN操作的返回值爲True。而當沒有找到,IN操作返回值爲False。讓我們假設我們想找到所有住在華盛頓州或喬治亞州的銷售部成員。我們可以寫一個帶着長長的WHERE 子句,並使用AND邏輯操作符的SQL語句,而使用IN操作符會縮短我們寫的語句。

SELECT *
FROM tblShipping
WHERE State IN ('WA','GA')


通過使用NOT邏輯操作符,我們可以檢索出IN操作的反操作結果,這個語句會返回所有不住在華盛頓州的銷售部成員。

SELECT *
FROM tblShipping
WHERE State NOT IN ('WA')


BETWEEN操作

BETWEEN操作用於判斷一個表達式的值是否介於一個特定的範圍之間。如果這個表達式的值介於這個特定範圍之間,包括範圍開始和結束的值,這個BETWEEN操作返回True。如果這個表達式得值不屬於這個範圍,則BETWEEN操作返回值爲False。假設我們想找到所以金額介於50美圓到100美圓之間的所有發票。我們最好在WHERE 子句使用BETWEEN 操作以及關鍵字AND設定範圍。

SELECT *
FROM tblInvoices
WHERE Amount BETWEEN 50 and 100


通過使用NOT邏輯操作符,我們可以檢索出BETWEEN操作的反操作結果,找到不在範圍中的所有發票數量。

SELECT *
FROM tblInvoices
WHERE Amount NOT BETWEEN 50 and 100


注意這個範圍可以設定爲相反的順序並依舊得到相同的結果 (BETWEEN 100 和 50),但許多的適用於ODBC的數據庫要求這個範圍遵從從頭到尾的順序。如果你設計你的應用程序可以兼容或升級爲適用於ODBC的數據庫,你就應該總是按照從頭到尾的方法使用。

LIKE操作
LIKE 操作operator is used to determine if the value of an expression compares to that of a pattern. 一個樣式就是就是一個完全的字符串或是一個包含有一個或多個通配符的部分字符串。通過使用LIKE 操作,你可以在一個結果集裏查找一個域並找到所有符合特殊的樣式的值。

SELECT *
FROM tblCustomers
WHERE [Last Name] LIKE 'Johnson'


爲了返回所有的名字以字母J開頭的顧客,我們使用星號通配符。

SELECT *
FROM tblCustomers
WHERE [Last Name] LIKE 'J*'


通過使用NOT邏輯操作符,我們可以檢索出LIKE操作的反操作,並在列表中過濾掉所有的 Johnsons。

SELECT *
FROM tblCustomers
WHERE [Last Name] NOT LIKE 'Johnson'


你在LIKE 操作樣式裏可以使用多種通配符,如下表所示:

通配符
描述

*(星號)
匹配所有字符並可以被用在結構字符串的任何位置。

%(百分號)
批評任何字符並可以被用在結構字符串的任何位置。(只適用於ADO 和 the Jet OLE DB provider)

?(問號)
匹配任何單個字符並可以被用在結構字符串的任何位置。

_(下劃線)
匹配任何單個字符並可以被用在結構字符串的任何位置。(只適用於ADO 和 the Jet OLE DB provider)

#(數字符號)
匹配任何單個數字並可以被用在結構字符串的任何位置。

[](方括號)
匹配任何被包括在方括號裏面的單個字符,並可以被用在結構字符串的任何位置。

!(感嘆號)
匹配任何不屬於被方括號所包含的字符列表中的單個字符。Matches any single character not in the list that is enclosed within the square brackets.

-(連字符)
匹配任何一個在方括號中的字符。


注意: 上表所述的“%”和“_”通配符只能通過Jet OLE DB provider 或 ADO運行。如果通過. Access SQL View 用戶界面運行它們將獲得一個空的結果集。

如果你想得到更多的通配符的信息,在Office 助理或微軟Access幫助窗體的Answer Wizard標誌中輸入wildcard characters,並單擊Search。

IS NULL 操作符
空值就是指無值或不可知值。IS NULL操作符被用於判斷一個表達式的值是否和一個空值相等。

SELECT *
FROM tblInvoices
WHERE Amount IS NULL


通過添加NOT邏輯操作符,我們可以檢索IS NULL操作符的反操作。在這個例子裏,SQL語句將會除掉所有包含丟失的或未知值的發票記錄。

SELECT *
FROM tblInvoices
WHERE Amount IS NOT NULL

SELECT INTO 語句
SELECT INTO 語句,也可以理解爲一個表單創建查詢,可以用來從一個或多個已存在工作表中創建一個新的工作表。它所創建的工作表可以基於任何有效的SELECT語句。SELECT INTO 語句可以用來存儲記錄、創建備份表單或在一個外部數據庫裏創建新的工作表。

當你用SELECT INTO 語句創建一個新工作表時,所有的新工作表裏的域都繼承於原始工作表。然而,不包括其他的工作表屬性,如主關鍵字或索引都是在新工作表中被創建。一旦新的工作表被創建,你當然可以使用ALTER TABLE語句添加這些屬性。

如果你要創建一個新的工作表,可以使用一個帶有你希望在工作表種包含的列的域列表和你新工作表的名稱的SELECT INTO 語句,並在FROM子句裏提供數據資源。

SELECT *
INTO tblNewCustomers
FROM tblCustomers


爲了爲新的工作表指定確定的域,把域名列表裏的原始工作表的域名用星號代替,並用AS關鍵字來命名新的工作表中的各列。

SELECT [First Name] & ' ' & [Last Name] AS FullName
INTO tblNewCustomerNames
FROM tblCustomers


如果要在一個已經存在的外部數據庫裏創建新的工作表,你可以用IN關鍵字。如果外部數據庫不存在,SELECT INTO 語句將會返回一個錯誤信息。

SELECT *
INTO tblNewCustomers
IN 'C:/Customers.mdb'
FROM tblCustomers


子查詢
子查詢就是在用在另一個SELECT、SELECT INTO、INSETT INTO 、DELETE 或UPDATE語句內部的SELECT語句。它可以幫助你對基於另一個結果集的結果進行進一步的限制。這叫做嵌入,並且因爲一個子查詢就是一個SELECT語句,你也可以把一個子查詢嵌入到另一個子查詢裏面。當你在一個SQL語句中使用一個子查詢的時候,它可以作爲一個域列表、WHERE子句或者HAVING子句的一部分。

這裏由三種基本的子查詢形式,並且每種都使用不同種類的謂詞。

IN子查詢
IN 子查詢用於檢索這樣的一組值,即其中記錄的某一列的值都爲另一個工作表或查詢中的一列的值包含。它從其它工作表中只能返回一列,這是一個限制條件。如果返回的多於一列就會產生一個錯誤。使用發票數據庫例子,我們可以寫出一個返回所有擁有發票的顧客的列表的SQL語句。

SELECT *
FROM tblCustomers
WHERE CustomerID
IN (SELECT CustomerID FROM tblInvoices)


通過使用NOT邏輯操作符,我們可以檢索和IN子查詢相反的記錄,從而可以獲得所有沒有任何發票的顧客列表。

SELECT *
FROM tblCustomers
WHERE CustomerID
NOT IN (SELECT CustomerID FROM tblInvoices)


ANY/SOME/ALL子查詢

ANY、 SOME和ALL子查詢謂詞被用於比較主查詢的記錄和子查詢的多個輸出記錄。ANY 和 SOME謂詞是同義詞並可以被替換使用。

當你需要從主查詢中檢索任何符合在子查詢中滿足比較條件的記錄時可以使用ANY或 SOME謂詞。謂詞應該恰好放在子查詢開始的括號前面。

SELECT *
FROM tblCustomers
WHERE CustomerID = ANY
(SELECT CustomerID FROM tblInvoices)


注意由上面SQL語句所返回的結果集和IN子查詢例子所返回的那個相同。而與ANY和SOME謂詞的不同之處就在於它們都可以使用等於(=)以外的操作符,比如大於(>)和小於(<)。

SELECT *
FROM tblCustomers
WHERE CustomerID > ANY
(SELECT CustomerID FROM tblInvoices)


當我們想在主查詢中檢索滿足子查詢比較條件的所有記錄時使用謂詞ALL。

SELECT *
FROM tblCustomers
WHERE CustomerID > ALL
(SELECT CustomerID FROM tblInvoices)


EXISTS子查詢

EXISTS謂詞是用於子查詢來在一個結果集中檢查所以存在值的記錄。換句話說,就是如果子查詢沒有返回任何行,這個比較就False。而如果它返回了一行或多行,這個比較就爲True。

SELECT *
FROM tblCustomers AS A
WHERE EXISTS
(SELECT * FROM tblInvoices
WHERE A.CustomerID = tblInvoices.CustomerID)


注意在前面的SQL 語句裏, tblCustomers 工作表使用了一個別名。這就是爲何我們可以在後來的子查詢中引用它的原因。當一個子查詢以這種格式與一個主查詢聯接時就稱相關查詢。

通過使用NOT邏輯操作符,我們可以檢索和EXISTS子查詢相反的記錄,從而可以得到所有沒有任何發票的顧客的結果集。

SELECT *
FROM tblCustomers AS A
WHERE NOT EXISTS
(SELECT * FROM tblInvoices
WHERE A.CustomerID = tblInvoices.CustomerID)


如果你想得到更多的關於子查詢的信息,在Office 助理或微軟Access幫助窗體的Answer Wizard標誌中輸入SQL subqueries ,並單擊Search。

連接
在一個如同Access的相關數據庫系統中,你會常常需要同時從多個工作表中摘出信息記錄。這可以通過使用一個SQL JOIN語句來實現。JOIN語句可以讓你從已經定義了相互關係的工作表中檢索記錄,而不用管記錄和工作表之間的關係是一對一、一對多還是多對多。

內部連接
內部連接,也被理解爲對等連接,就是被使用的連接裏最一般的形式。這種連接通過匹配一個各個工作表中共有的域值來從兩個或更多的工作表中檢索記錄。你所連接的域必須具有類似的數據類型,但你就不能對MOMO和OLEOBJECT數據類型進行連接。爲了建立一個INNER JOIN語句,在SELECT語句的FROM子句裏使用INNER JOIN關鍵字。讓我們使用INNER JOIN 建立所有擁有發票的顧客的結果集,並帶上那些發票的時間和金額。

SELECT [Last Name], InvoiceDate, Amount
FROM tblCustomers INNER JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID
ORDER BY InvoiceDate


注意工作表名被INNER JOIN關鍵字所分開,並且相關的比較是在ON關鍵字的後面。對於相關的比較,你也可以使用<、 >、 <=、 >=或 <> 操作符,並且你也可以使用BETWEEN關鍵字。同時注意各個工作表只在比較關係中使用的ID域,它們都不是最後結果集的組成。

如果要進一步的限制SELECT 語句我們可以在ON子句中的比較連接後面使用WHERE子句。在下面的例子中我們通過只包括1998年1月1日以後的發票來縮小結果集。

SELECT [Last Name], InvoiceDate, Amount
FROM tblCustomers INNER JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID
WHERE tblInvoices.InvoiceDate > #01/01/1998#
ORDER BY InvoiceDate


在希望連接多個工作表的案例中,你可以嵌入INNER JOIN子句。在這個例子裏,我們將在過去的一個SELECT語句的基礎上產生我們的結果集,但我們也將通過爲tblShipping工作表添加INNER JOIN使結果包括每個顧客的所在城市和國家。

SELECT [Last Name], InvoiceDate, Amount, City, State
FROM (tblCustomers INNER JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID)
INNER JOIN tblShipping
ON tblCustomers.CustomerID=tblShipping.CustomerID
ORDER BY InvoiceDate


注意第一個JOIN子句爲圓括號所包含以使之從邏輯上和第二個JOIN子句分開。而在FROM子句中使用一個第二個工作表的別名把一個工作表連接到自身也是可能的。讓我們假設我們想找到所有具有相同的名的顧客記錄。我們可以通過爲第二個工作表創建一個別名“A”並查找其姓氏不同的記錄來實現。

SELECT tblCustomers.[Last Name],
tblCustomers.[First Name]
FROM tblCustomers INNER JOIN tblCustomers AS A
ON tblCustomers.[Last Name]=A.[Last Name]
WHERE tblCustomers.[First Name]<>A.[First Name]
ORDER BY tblCustomers.[Last Name]


外部連接

外部連接是在當記錄保存在某一個工作表中時用於在多個工作表進行記錄檢索,即使在其它的工作表中沒有匹配的記錄也行。Jet 數據庫引擎共支持兩種類型的外部連接。考慮兩個互相相近的工作表,一個在左邊,另一個在右邊。左外部連接將在右工作表中選擇所有匹配比較關係標準的所有行和左工作表中的所有行,即使在右工作表中沒有匹配記錄存在。而右外部連接則是左外部連接的簡單反轉;即所有在右工作表中的行將被保存。

作爲一個例子,讓我們假設我們想測定每個顧客的所有發票數量,但如果一個顧客沒有發票,我們希望通過消息“NONE”來顯示其信息。

SELECT [Last Name] & ', ' & [First Name] AS Name,
IIF(Sum(Amount) IS NULL,'NONE',Sum(Amount)) AS Total
FROM tblCustomers LEFT OUTER JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID
GROUP BY [Last Name] & ', ' & [First Name]


在前面的SQL語句中仍然有幾個問題。第一個是對字符串連接操作符“&”的使用,這個操作符允許你把兩個或更多的域連接到一起組成一個字符串。第二個是 immediate if(IIF)語句,它會檢查合併後的字符串是否爲空。如果爲空,這個語句將返回消息“NONE”,而如果組合不是空,將返回組合後的值。最後一點是外部連接子句。使用左外部連接保存左工作表的行從而讓我們可以看到所有的顧客,包括那些沒有發票在帳目中的。

在一個多工作表的連接中外部連接可以被嵌套在內部連接裏,但內部連接不可以被嵌套在外部連接中。

笛卡兒乘積
當我們討論聯接時常常遇到的一個術語是笛卡兒乘積。笛卡兒乘積的定義爲“把所有表單的所有行完全合併”。例如,如果你想不用任何約束把兩個工作表聯合在一起,你就完成了一個笛卡兒乘積。

SELECT *
FROM tblCustomers, tblInvoices


這不是一個好東西,特別當你要處理的工作表中包含有成百上千行數據時。所以你應該通過約束你的連接來避免笛卡兒乘積。

The UNION operator
雖然UNION 的操作也可以視爲一個合併查詢,但我們不可以技術性地把它看作是一個聯接,它之所以被提到是因爲它能把從多個來源獲得的數據合成一個結果表單中,而這一點和某些類型的聯接是類似的。UNION 操作一般被用來把來自表單、SELECT語句或查詢的數據結合,並省略掉任何重複的行。所有的數據源必須有相同數目的域,不過這些域不一定要是相同的數據類型。讓我們假設我們有一個僱員表單,其中具有和顧客工作表單相同的結構,那麼我們希望合併這兩個工作表得到一個姓名和電子郵件地址信息的列表。

SELECT [Last Name], [First Name], Email
FROM tblCustomers
UNION
SELECT [Last Name], [First Name], Email
FROM tblEmployees


如果你希望找到這些表中的所有域,我們可以使用TABLE關鍵字,如同下面一樣:

TABLE tblCustomers
UNION
TABLE tblEmployees


UNION操作不會顯示任何在兩個表單中重複出現的記錄,但它可以通過在UNION關鍵字後使用謂詞ALL來覆蓋重複信息,如下所示:

SELECT [Last Name], [First Name], Email
FROM tblCustomers
UNION ALL
SELECT [Last Name], [First Name], Email
FROM tblEmployees


轉換語句

雖然轉換語句也可以視爲一個交叉表查詢,但我們不可以技術性地把它看作是一個聯接,它之所以被提到是因爲它能把從多個來源獲得的數據合成一個結果表單中,而這一點和某些類型的聯接是類似的。

TRANSFORM 語句通常用於計算總數、平均值、數目以及其它對記錄進行總體統計的算法。並在計算後把結果信息顯示在一個格子或數據表中,其中的數據分別按照行和列排列。一個TRANSFORM 語句的一般形式如下:

TRANSFORM aggregating function
SELECT Statement
PIVOT column heading field


我們假設我們可以建立一個按照每一年爲基礎顯示每個顧客的所有發票的數據表。這個列名應該是顧客的姓名,而行名則將是年份。讓我們修改原來的SQL語句以符合轉變後的語句.

TRANSFORM
IIF(Sum([Amount]) IS NULL,'NONE',Sum([Amount]))
AS Total
SELECT [Last Name] & ', ' & [First Name] AS Name
FROM tblCustomers LEFT JOIN tblInvoices
ON tblCustomers.CustomerID=tblInvoices.CustomerID
GROUP BY [Last Name] & ', ' & [First Name]
PIVOT Format(InvoiceDate, 'yyyy')
IN ('1996','1997','1998','1999','2000')


注意SUM函數是合計函數,組裏的列的題頭用在SELECT 語句的子句裏,而行的名字由PIVOT關鍵字後所列出的域名決定。

如果你想知道關於連接的更多信息,在Office 助理或微軟Access幫助窗體得Answer Wizard標誌中輸入SQL joins,並單擊Search。

 


現在我們已經討論了中級SQL的語法,那麼讓我們看看在一個Access應用程序中我們可以使用它的一些途徑。

數據庫範例
作爲這篇文章的附帶,這裏有一個叫acIntSQL.mdb的數據庫範例。

在acIntSQL中的任一處都是基於本文所提到的所有主題,並且它通過查詢和範例的代碼演示了我們所討論的不同SQL語句。

在acIntSQL中所使用到的許多部分查詢都是基於特定工作表中存在和包含的數據,或者是基於其它已經存在的數據庫對象。如果你由於丟失數據而在運行一個查詢產生故障,打開工作表重置窗體並單擊工作表重置按鍵。這將會重新生產工作表和其中原始缺省數據。如果要手動通過工作表重置過程,你需要按照下面的順序執行這些查詢過程:

Drop Table Shipping
Drop Table Invoices
Drop Table Customers
Drop Table CreditLimit
Create Table Customers
Create Table Invoices
Create Table Shipping
Create Table CreditLimit
Populate Customers
Populate Invoices
Populate Shipping
Populate CreditLimit

查詢
查詢就是指存儲在Access數據庫中並可以隨時調用的SQL 語句,也可以直接被Access 用戶界面或Visual Basic? for Applications (VBA)編程語言調用。查詢可以使用Access Query Designer來建立,Access Query Designer時一個可以很容易建立SQL語句的強大的可視化工具。或者你也可以通過直接在SQL視圖窗口輸入SQL語句來建立查詢。

如同在"Microsoft Jet SQL for Access 2000基礎篇"一文中所述, Access把數據庫中所有面向數據的任務轉化爲SQL 語句。要演示這一點,讓我們使用Access Query Designer來建立一個查詢。

打開acIntSQL數據庫。
(單擊此處拷貝acIntSQL.mdb 數據庫例子。)

確保tblCustomers 和 tblInvoices這兩個表單已經創建並且其中包含有數據。
在數據庫窗口中從Objects條中選擇Queries選項。
在數據庫窗口工具條裏單擊按鍵 New。
在New Query對話框中選擇Design View並單擊OK。
在Show Table對話框中選擇tblCustomers並單擊Add;接着選擇tblInvoices 並單擊Add;接着單擊Close按鍵。
在tblCustomers 域名列表中選擇Last Name 域並把它拖到設計表格中的第一個域中。
在tblInvoices 域名列表中選擇InvoiceDate 和 Amount域並把它們拖到設計表格中。
在設計表格中InvoicwDate域的Sort屬性裏選擇Ascending。
從Access菜單條中選擇View並單擊SQL View。這樣就打開了SQL View 窗口和顯示了在查詢中Access正在使用的SQL語法。
注意 這個查詢類似於存儲在acIntSQL 數據庫中的"Join - Inner"查詢。

嵌入語句
嵌入SQL 語句就是指你在Visual Basic for Applications (VBA) 編程語言中使用SQL 語句。雖然深入討論如何使用VBA超出了本文的範圍,但如何使用程序來運行SQL 語句卻是一件簡單的工作。

在acIntSQL數據庫中,有兩個使用內部SQL語句的窗體需要通過Jet OLE DB provider 和 ADO來運行:就是演示數據定義語句的 Intermediate DDL 窗體,以及演示數據處理語句的Intermediate DML窗體。

中級DDL 語句
這個acIntSQL數據庫有許多關於你可以用來管理你的數據庫結構的SQL 語句的範例。有一部分數據定義語言 (DDL) 語句被以數據定義查詢的方式存儲。而其它的則在程序設計代碼的內部作爲內聯SQL使用。如果你要使用這些DDL例子,你需要在運行它之前刪除一些數據庫對象。例如,如果你想運行創建當前數據類型的查詢,你就先要確定當前數據表單不存在。如果不是,那麼,這個查詢就會返回一個信息告訴你這個表單已經存在。在運行任何DDL 例子之前,檢查它所要創建或改變的數據庫對象確定其已經被設定好,這樣程序才能完全的運行。

在內聯DDL 語句範例中,同樣的建議仍然是適用的:檢查並設定它們會影響的數據庫對象以確保DDL 語句的順利運行。

一般來說,內聯DDL 語句只是通過簡單設定一個ADO Connection對象來運行,並將SQL 語句傳送給 Connection對象的運行程序。下面是來源於在中級DDL語句窗體的二進制數據類型的輸入輸出。

Private Sub cmdBinary_Click() Dim conDatabase As ADODB.Connection
Dim SQL As String
On Error GoTo Error_Handler
Set conDatabase = Application.CurrentProject.Connection
'注意: Fields 1 through 4 can be created through both
'SQL View and the Jet OLEDB Provider.
'Fields 5 and 6 can only be created through the
'Jet OLE DB provider.

SQL = "CREATE TABLE tblCodeBinaryDataTypes (" & _
"Field1_BINARY BINARY, " & _
"Field2_BINARY250 BINARY(250), " & _
"Field3_VARBINARY VARBINARY, " & _
"Field4_VARBINARY250 VARBINARY(250), " & _
"Field5_BVARYING BINARY VARYING, " & _
"Field6_BVARYING250 BINARY VARYING(250))"
conDatabase.Execute SQL
MsgBox "The BINARY datatypes table has been created!"
conDatabase.Close
Set conDatabase = Nothing
Exit Sub
Error_Handler:
MsgBox Err.Description, vbInformation
End Sub

 


運行過其中一個DDL 語句後,在設計視圖中打開被影響的數據庫查看產生了什麼變動。如果DDL 語句影響了表單之間的關聯,打開編輯關聯窗口查看其變動。例如讓我們檢查一下在中級DDL語句窗體中的Alter Table w/ Fast Foreign Key輸出指令和按鍵。
打開acIntSQL 數據庫。
確定tblCustomers 和 tblInvoices 表單已經被創建。
在數據庫窗口從Objects條中選擇Forms。
在數據庫窗口工具條中着重顯示Intermediate DDL 語句的窗體並單擊Design按鍵。
在Intermediate DDL 語句窗體中,鼠標右鍵點擊Alter Table w/ Fast Foreign Key按鍵並從彈出菜單中選擇 Build Event…。這操作將打開VBA開發環境以及包含着cmdFastKey_Click子過程的代碼窗口。
檢查被分配給 SQL變量的SQL 語句。
SQL = "ALTER TABLE tblInvoices " & _
"ADD CONSTRAINT FK_tblInvoices " & _
"FOREIGN KEY NO INDEX (CustomerID) REFERENCES " & _
"tblCustomers (CustomerID) " & _
"ON UPDATE CASCADE " & _
"ON DELETE CASCADE"


注意 DDL 語句改變了tblInvoices 表單並添加了牢固的外關鍵字限制。同時它也通過使用級聯子句在tblInvoices 和 tblCustomers 之間建立了一個數據關聯。

關閉VBA 開發環境。
關閉Intermediate DDL 語句窗體。
從Tools菜單中,選擇Relationships…菜單項以打開關聯窗口。
雙擊tblCustomers 和 tblInvoices 之間的關聯鏈接以打開Edit Relationships對話框。
注意級聯性更新和刪除選項沒有被設置。
關閉對話框。
當關聯鏈接仍然顯示時,按Delete鍵刪除聯接。
關閉關聯窗口。
如果Intermediate DDL 語句在數據庫窗口仍然顯示,點擊數據庫窗口工具條中的Open按鍵。
點擊Alter Table w/ Fast Foreign Key按鍵產生一個外關鍵字聯繫。
關閉Intermediate DDL 語句窗體。
當新的關係鏈接被創建後,使用前面提到的步驟打開Edit Relationships對話框。
注意級聯性更新和刪除選項已經被設置。
中級 DML 語句
這個acIntSQL數據庫有許多關於數據處理語言 (DML) 語句的例子,在這些範例裏你可以用它們來找到數據,並且它們中的大多數是以查詢的形式實現的。僅有的以在線SQL形式實現的DML 語句則是基於中級DML 語句窗體的。窗體中的三個例子在LIKE子句中使用"_" 和 "%" 通配符,並使用SELECT INTO 語句在一個外部數據庫中創建一個表單。

在acIntSQL 數據庫中保存的兩個查詢是屬於DML 語句內容卻執行類似DDL的操作。其中的SELECT INTO 語句從已有的數據庫中找到數據並用這些數據創建新的工作表。通過這些範例的學習,你將學會如何刪除目標工作表,前提是這些工作表已經存在。

在中級DML語句的窗體中的Create Customers Database輸出指令和按鍵展示了一個對SELECT INTO 語句的有趣應用。這是一個告訴你使用中級SQL 語句所能完成的各種事情的一個好的例子。下面就是關於輸出命令和按鍵的子過程的代碼:

Private Sub cmdCreateDB_Click()
Dim conCatalog As ADOX.Catalog
Dim conDatabase As ADODB.Connection
Dim SQL As String
Dim sDBName As String
On Error GoTo Error_Handler
'Initialize objects & variables.
Set conDatabase = Application.CurrentProject.Connection
Set conCatalog = New ADOX.Catalog
sDBName = "C:/Customers.mdb"
'Create the Customers database.
conCatalog.Create "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & sDBName
'Run the DML statement to build the Customers table.
SQL = "SELECT * INTO tblCustomers IN '" & sDBName & _
"'" & "FROM tblCustomers"
conDatabase.Execute SQL
MsgBox "The new CUSTOMERS database has been created " & _
"as " & sDBName & ".", vbInformation
conDatabase.Close
Set conDatabase = Nothing
Set conCatalog = Nothing
Exit Sub
Error_Handler:
MsgBox Err.Description, vbInformation
End Sub


如果客戶數據庫已經存在,那麼代碼將返回一個信息告訴你這個數據庫無法被創建。讓我們逐步的運行這個代碼來看看它都做了什麼。

堅持你的C:驅動器確定Customers.mdb文件不存在,如果存在就刪除它。
打開acIntSQL 數據庫。
確定tblCustomers數據庫已經被創建並且此數據庫已經裝載了數據。
在數據庫窗口從Objects條中選擇Forms。
在數據庫窗口工具條中着重顯示Intermediate DM 語句的窗體並單擊Open按鍵。
單擊Create Customers Database按鍵創建新的數據庫。
切換到資源管理器查看你的C盤驅動器內容。Customers.mdb 數據庫文件應該已經被創建。
雙擊Customers.mdb數據庫文件以打開另一個Access實例。
打開tblCustomers 數據庫。注意它所包含的數據和 acIntSQL 數據庫裏的tblCustomers 所包含的數據相同。
這個產生新的數據庫的代碼範例是通過Jet OLE DB provider使用ADOX 對象庫來創建Access數據庫。對於ADOX 對象庫的討論已經超出了本文的範圍。如果你想知道更多關於它的信息,在Access 2000 在線幫助中查找"Microsoft ActiveX Data Objects (ADO)"並打開其目錄直到你看見"Microsoft ADO Extensions for DDL和 Security (ADOX) Programmer's Reference"。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章