多數SQL查詢只包含從一個或多個表中返回數據的單條 SELECT 語句。可是,SQL 也容許執行多個查詢(多條 SELECT 語句),並將結果做爲一個查詢結果集返回。這些組合查詢一般稱爲並(union)或複合查詢(compound query)。程序員
主要有兩種狀況須要使用組合查詢:sql
能夠用 UNION 操做符來組合數條 SQL 查詢。數據庫
使用 UNION 很簡單,所要作的只是給出每條 SELECT 語句,在各條語句之間放上關鍵字 UNION。安全
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';
複製代碼
使用多條WHERE子句而不是UNION的相同查詢:服務器
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
OR cust_name = 'Fun4All';
複製代碼
對於較複雜的過濾條件,或者從多個表(而不是一個表)中檢索數據的情形,使用 UNION 可能會使處理更簡單。數據庫設計
UNION 從查詢結果集中自動去除了重複的行;換句話說,它的行爲與一條 SELECT 語句中使用多個 WHERE 子句條件同樣。函數
若是想返回全部的匹配行,可以使用 UNION ALL 而不是 UNION。工具
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
UNION ALL
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All';
複製代碼
UNION ALL 爲 UNION 的一種形式,它完成 WHERE 子句完成不了的工做。佈局
在用 UNION 組合查詢時,只能使用一條 ORDER BY 子句,它必須位於最後一條 SELECT 語句以後。性能
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All'
ORDER BY cust_name, cust_contact;
複製代碼
INSERT 用來將行插入(或添加)到數據庫表。插入有幾種方式:
插入及系統安全:使用 INSERT 語句可能須要客戶端/服務器 DBMS 中的特定安全權限。在你試圖使用 INSERT 前,應該保證本身有足夠的安全權限。
把數據插入表中的最簡單方法是使用基本的 INSERT 語法,它要求指定表名和插入到新行中的值。
INSERT INTO Customers
VALUES('1000000006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA', NULL, NULL);
複製代碼
存儲到表中每一列的數據在 VALUES 子句中給出,必須給每一列提供一個值。若是某列沒有值,則應該使用 NULL 值(假定表容許對該列指定空值)。各列必須以它們在表定義中出現的次序填充。
雖然這種語法很簡單,但並不安全,應該儘可能避免使用。上面的 SQL 語句高度依賴於表中列的定義次序,還依賴於其容易得到的次序信息。即便能夠獲得這種次序信息,也不能保證各列在下一次表結構變更後保持徹底相同的次序。所以,編寫依賴於特定列次序的 SQL 語句是很不安全的,這樣作早晚會出問題。
編寫 INSERT 語句的更安全(不過更繁瑣)的方法以下:
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA', NULL, NULL);
複製代碼
由於提供了列名,VALUES 必須以其指定的次序匹配指定的列名,不必定按各列出如今表中的實際次序。其優勢是,即便表的結構改變,這條 INSERT 語句仍然能正確工做。
給出列名的狀況下,以不一樣的次序填充仍然正確:
INSERT INTO Customers(cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip)
VALUES('1000000006', NULL, NULL, 'Toy Land', '123 Any Street', 'New York', 'NY', '11111');
複製代碼
當心使用 VALUES:無論使用哪一種 INSERT 語法,VALUES 的數目都必須正確。若是不提供列名,則必須給每一個表列提供一個值;若是提供列名,則必須給列出的每一個列一個值。不然,就會產生一條錯誤消息,相應的行不能成功插入。
使用 INSERT 的推薦方法是明確給出表的列名。使用這種語法,還能夠省略列,這表示能夠只給某些列提供值,給其餘列不提供值。
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
VALUES('1000000006', 'Toy Land', '123 Any Street', 'New York', 'NY', '11111', 'USA');
複製代碼
省略的列必須知足如下條件:
INSERT 還存在另外一種形式,能夠利用它將 SELECT 語句的結果插入表中,這就是所謂的INSERT SELECT。顧名思義,它是由一條 INSERT語句和一條 SELECT語句組成的。
INSERT INTO Customers(cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
SELECT cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country
FROM CustNew;
複製代碼
若是 CustNew 這個表確實有數據,則全部的數據將被插入到 Customers 表。
有一種數據插入不使用 INSERT 語句。要將一個表的內容複製到一個全新的表(運行中建立的表),可使用 SELECT INTO 語句。
SELECT *
INTO CustCopy
FROM Customers;
複製代碼
要想只複製部分的列,能夠明確給出列名,而不是使用 * 通配符。
在使用SELECT INTO時,須要知道一些事情:
更新(修改)表中的數據,可使用 UPDATE 語句。有兩種使用 UPDATE 的方式:
基本的 UPDATE 語句由三部分組成,分別是:
UPDATE Customers
SET cust_email = 'kim@thetoystore.com WHERE cust_id = '1000000005'; 複製代碼
不要省略 WHERE 子句:在使用 UPDATE 時必定要細心。由於稍不注意,就會更新表中的全部行。
更新更多列的語法稍有不一樣:
UPDATE Customers
SET cust_contact = 'Sam Roberts',
cust_email = 'sam@toyland.com'
WHERE cust_id = '1000000006';
複製代碼
要刪除某個列的值,可設置它爲 NULL(假如表定義容許 NULL 值)。
UPDATE Customers
SET cust_email = NULL
WHERE cust_id = '1000000005'
複製代碼
其中 NULL 用來去除 cust_email 列中的值。這與保存空字符串很不一樣(空字符串用''表示,是一個值),而 NULL 表示沒有值。
從一個表中刪除(去掉)數據,使用 DELETE 語句。有兩種使用 DELETE 的方式:
DELETE FROM Customers
WHERE cust_id = '1000000006';
複製代碼
不要省略 WHERE 子句:在使用 DELETE 時必定要細心。由於稍不注意,就會錯誤地刪除表中全部行。
友好的外鍵:使用外鍵確保引用完整性的一個好處是,DBMS 一般能夠防止刪除某個關係須要用到的行。例如,要從 Products 表中刪除一個產品,而這個產品用在 OrderItems 的已有訂單中,那麼 DELETE 語句將拋出錯誤並停止。這是總要定義外鍵的另外一個理由。
若是省略了 WHERE 子句,則 UPDATE 或 DELETE 將被應用到表中全部的行。所以許多 SQL 程序員使用 UPDATE 或 DELETE 時須要遵循如下原則:
通常有兩種建立表的方法:
利用 CREATE TABLE 建立表,必須給出下列信息:
CREATE TABLE Products
(
prod_id CHAR(10) NOT NULL,
vend_id CHAR(10) NOT NULL,
prod_name CHAR(254) NOT NULL,
prod_price DECIMAL(8, 2) NOT NULL,
prod_desc VARCHAR(1000) NULL
);
複製代碼
替換現有的表:在建立新的表時,指定的表名必須不存在,不然會出錯。防止意外覆蓋已有的表,SQL 要求首先手工刪除該表(請參閱後面的內容),而後再重建它,而不是簡單地用建立表語句覆蓋它。
在插入或更新行時,該列必須有值。每一個表列要麼是 NULL列,要麼是 NOT NULL 列,這種狀態在建立時由表的定義規定。
CREATE TABLE Orders
(
order_num INTEGER NOT NULL,
order_date DATETIME NOT NULL,
cust_id CHAR(10) NOT NULL
);
複製代碼
這三列都須要,所以每一列的定義都含有關鍵字 NOT NULL。這就會阻止插入沒有值的列。若是插入沒有值的列,將返回錯誤,且插入失敗。
CREATE TABLE Vendors
(
vend_id CHAR(10) NOT NULL,
vend_name CHAR(50) NOT NULL,
vend_address CHAR(50) ,
vend_city CHAR(50) ,
vend_state CHAR(5) ,
vend_zip CHAR(10) ,
vend_country CHAR(50)
);
複製代碼
NULL 爲默認設置,若是不指定 NOT NULL,就認爲指定的是 NULL。
主鍵和 NULL 值:主鍵是其值惟一標識表中每一行的列。只有不容許 NULL 值的列可做爲主鍵,容許 NULL 值的列不能做爲惟一標識。
CREATE TABLE OrderItems
(
order_num INTEGER NOT NULL,
order_item INTEGER NOT NULL,
prod_id CHAR(10) NOT NULL,
quantity INTEGER NOT NULL DEFAULT 1,
item_price DECIMAL(8, 2) NOT NULL
);
複製代碼
默認值常常用於日期或時間戳列。
更新表定義,可使用 ALTER TABLE 語句。如下是使用 ALTER TABLE 時須要考慮的事情。
使用 ALTER TABLE 更改表結構,必須給出下面的信息:
ALTER TABLE Vendors
ADD vend_phone CHAR(20);
複製代碼
更改或刪除列、增長約束或增長鍵,這些操做也使用相似的語法:
ALTER TABLE Vendors
DROP COLUMN vend_phone;
複製代碼
複雜的表結構更改通常須要手動刪除過程,它涉及如下步驟:
(1) 用新的列布局建立一個新表; (2) 使用 INSERT SELECT 語句(關於這條語句的詳細介紹,請參閱第 15課)從舊錶複製數據到新表。有必要的話,可使用轉換函數和計算字段; (3) 檢驗包含所需數據的新表; (4) 重命名舊錶(若是肯定,能夠刪除它); (5) 用舊錶原來的名字重命名新表; (6) 根據須要,從新建立觸發器、存儲過程、索引和外鍵。
當心使用 ALTER TABLE:使用 ALTER TABLE 要極爲當心,應該在進行改動前作完整的備份(表結構和數據的備份)。數據庫表的更改不能撤銷,若是增長了不須要的列,也許沒法刪除它們。相似地,若是刪除了不該該刪除的列,可能會丟失該列中的全部數據。
DROP TABLE CustCopy;
複製代碼
刪除表沒有確認,也不能撤銷,執行這條語句將永久刪除該表。
使用關係規則防止意外刪除:許多 DBMS 容許強制實施有關規則,防止刪除與其餘表相關聯的表。在實施這些規則時,若是對某個表發佈一條 DROP TABLE 語句,且該表是某個關係的組成部分,則DBMS將阻止這條語句執行,直到該關係被刪除爲止。若是容許,應該啓用這些選項,它能防止意外刪除有用的表。
全部重命名操做的基本語法都要求指定舊錶名和新表名。不過,存在 DBMS 實現差別。關於具體的語法,請參閱相應的 DBMS 文檔。
視圖是虛擬的表。與包含數據的表不同,視圖只包含使用時動態檢索 數據的查詢。
用下面的 SELECT 語句從三個表中檢索數據:
SELECT cust_name, cust_contact
FROM Customers, Orders, OrderItems
WHERE Customer.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num
AND prod_id = 'RGAN01';
複製代碼
如今,假如能夠把整個查詢包裝成一個名爲 ProductCustomers 的虛擬表,則能夠以下輕鬆地檢索出相同的數據:
SELECT cust_name, cust_contact
FROM ProductCustomers
WHERE prod_id = 'RGAN01';
複製代碼
這就是視圖的做用。ProductCustomers 是一個視圖,它不包含任何列或數據,包含的是一個查詢(與上面用以正確聯結表的查詢相同)。
下面是視圖的一些常見應用:
建立視圖以後,能夠用與表基本相同的方式使用它們。能夠對視圖執行 SELECT 操做,過濾和排序數據,將視圖聯結到其餘視圖或表,甚至添加和更新數據(添加和更新數據存在某些限制,關於這個內容稍後作介紹)。
重要的是,要知道視圖僅僅是用來查看存儲在別處數據的一種設施。視圖自己不包含數據,所以返回的數據是從其餘表中檢索出來的。在添加或更改這些表中的數據時,視圖將返回改變過的數據。
性能問題:由於視圖不包含數據,因此每次使用視圖時,都必須處理查詢執行時須要的全部檢索。若是你用多個聯結和過濾建立了複雜的視圖或者嵌套了視圖,性能可能會降低得很厲害。所以,在部署使用了大量視圖的應用前,應該進行測試。
關於視圖建立和使用的一些最多見的規則和限制:
視圖用 CREATE VIEW 語句來建立。刪除視圖能夠用 DROP VIEW 。
CREATE VIEW ProductCustomers AS
SELECT cust_name, cust_contact, prod_id
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num;
複製代碼
在以上視圖中進行檢索:
SELECT cust_name, cust_contact
FROM ProductCustomers
WHERE prod_id = 'RGAN01';
複製代碼
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title
FROM Vendors
ORDER BY vend_name;
複製代碼
把此語句轉換爲視圖:
CREATE VIEW VendorLocations AS
SELECT RTRIM(vend_name) + ' (' + RTRIM(vend_country) + ')' AS vend_title
FROM Vendors;
複製代碼
再檢索數據:
SELECT *
FROM VendorLocations;
複製代碼
CREATE VIEW CustomerEmailList AS
SELECT cust_id, cust_name, cust_email
FROM Customers
WHERE cust_email IS NOT NULL;
複製代碼
再檢索數據:
SELECT *
FROM CustomerEMailList;
複製代碼
SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price
FROM OrderItems
WHERE order_num = 20008;
複製代碼
將以上查詢轉成視圖:
CREATE VIEW OrderItemsExpanded AS
SELECT order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price
FROM OrderItems;
複製代碼
再檢索數據:
SELECT *
FROM OrderItemsExpanded
WHERE order_num = 20008;
複製代碼
簡單來講,存儲過程就是爲之後使用而保存的一條或多條 SQL 語句。可將其視爲批文件,雖然它們的做用不只限於批處理。
理由不少,下面給出一些主要的:
換句話說,使用存儲過程有三個主要的好處,即簡單、安全、高性能。
存儲過程的執行遠比編寫要頻繁得多,所以咱們先介紹存儲過程的執行。執行存儲過程的 SQL 語句很簡單,即 EXECUTE。EXECUTE 接受存儲過程名和須要傳遞給它的任何參數。
EXECUTE AddNewProduct('JTS01', 'Stuffed Eiffel Tower', 6.49, 'Plush stuffed toy with the text La Tour Eiffel in red white and blue'0;
複製代碼
這裏執行一個名爲 AddNewProduct 的存儲過程,將一個新產品添加到 Products 表中。AddNewProduct 有四個參數,分別是:供應商 ID(Vendors 表的主鍵)、產品名、價格和描述。這 4個參數匹配存儲過程當中4個預期變量(定義爲存儲過程自身的組成部分)。此存儲過程將新行添加到 Products 表,並將傳入的屬性賦給相應的列。
在 Products表中還有另外一個須要值的列 prod_id列,它是這個表的主鍵。爲何這個值不做爲屬性傳遞給存儲過程?要保證恰當地生成此 ID,最好是使生成此 ID 的過程自動化(而不是依賴於最終用戶的輸入)。
如下是存儲過程所完成的工做:
Oracle 版本:
CREATE PROCEDURE MailingListCount (
ListCount OUT INTEGER
)
IS
v_rows INTEGER;
BEGIN
SELECT COUNT(*) INTO v_rows
FROM Customers
WHERE NOT cust_email IS NULL;
ListCount := v_rows;
END;
複製代碼
這個存儲過程有一個名爲 ListCount 的參數。此參數從存儲過程返回一個值而不是傳遞一個值給存儲過程。關鍵字 OUT 用來指示這種行爲。Oracle支持 IN(傳遞值給存儲過程)、OUT(從存儲過程返回值,如這裏)、INOUT (既傳遞值給存儲過程也從存儲過程傳回值)類型的參數。存儲過程的代碼括在 BEGIN 和 END 語句中,這裏執行一條簡單的 SELECT 語句,它檢索具備郵件地址的顧客。而後用檢索出的行數設置 ListCount(要傳遞的輸出參數)。
使用事務處理(transaction processing),經過確保成批的 SQL 操做要麼徹底執行,要麼徹底不執行,來維護數據庫的完整性。
關係數據庫把數據存儲在多個表中,使數據更容易操縱、維護和重用。不用深究如何以及爲何進行關係數據庫設計,在某種程度上說,設計良好的數據庫模式都是關聯的。
事務處理是一種機制,用來管理必須成批執行的 SQL 操做,保證數據庫不包含不完整的操做結果。利用事務處理,能夠保證一組操做不會中途中止,它們要麼徹底執行,要麼徹底不執行(除非明確指示)。若是沒有錯誤發生,整組語句提交給(寫到)數據庫表;若是發生錯誤,則進行回退(撤銷),將數據庫恢復到某個已知且安全的狀態。
下面是關於事務處理須要知道的幾個術語:
能夠回退哪些語句:事務處理用來管理 INSERT、UPDATE 和 DELETE 語句。不能回退 SELECT 語句(回退 SELECT 語句也沒有必要),也不能回退 CREATE 或 DROP 操做。
管理事務的關鍵在於將 SQL 語句組分解爲邏輯塊,並明確規定數據什麼時候應該回退,什麼時候不該該回退。
MySQL 中的標識:
START TRANSACTION
...
複製代碼
事務一直存在,直到被中斷。一般,COMMIT 用於保存更改,ROLLBACK 用於撤銷,詳述以下。
DELETE FROM Orders;
ROLLBACK;
複製代碼
在此例子中,執行 DELETE 操做,而後用 ROLLBACK 語句撤銷。雖然這不是最有用的例子,但它的確可以說明,在事務處理塊中,DELETE 操做(與 INSERT 和 UPDATE 操做同樣)並非最終的結果。
通常的 SQL 語句都是針對數據庫表直接執行和編寫的。這就是所謂的隱式提交(implicit commit),即提交(寫或保存)操做是自動進行的。
在事務處理塊中,提交不會隱式進行。不過,不一樣 DBMS 的作法有所不一樣。有的 DBMS 按隱式提交處理事務端,有的則不這樣。
進行明確的提交,使用COMMIT語句。
Oracle 示例:
SET TRANSACTION
DELETE OrderItems WHERE order_num = 12345;
DELETE OrderItems WHERE order_num = 12345;
COMMIT;
複製代碼
使用簡單的 ROLLBACK 和 COMMIT 語句,就能夠寫入或撤銷整個事務。可是,只對簡單的事務才能這樣作,複雜的事務可能須要部分提交或回退。
要支持回退部分事務,必須在事務處理塊中的合適位置放置佔位符。這樣,若是須要回退,能夠回退到某個佔位符。
MySQL 和 Oracle 示例:
ROLLBACK TO delete1;
複製代碼
有時,須要在檢索出來的行中前進或後退一行或多行,這就是遊標的用途所在。遊標(cursor)是一個存儲在 DBMS 服務器上的數據庫查詢,它不是一條 SELECT 語句,而是被該語句檢索出來的結果集。在存儲了遊標以後,應用程序能夠根據須要滾動或瀏覽其中的數據。
不一樣的 DBMS 支持不一樣的遊標選項和特性。常見的一些選項和特性以下:
使用遊標有幾個明確的步驟:
使用 DECLARE 語句建立遊標,這條語句在不一樣的 DBMS 中有所不一樣。DECLARE 命名遊標,並定義相應的 SELECT 語句,根據須要帶 WHERE 和其餘子句。
DECLARE CustCursor CURSOR
FOR
SELECT * FROM Customers
WHERE cust_email IS NULL;
複製代碼
OPEN CURSOR CustCursor;
複製代碼
如今能夠用 FETCH 語句訪問遊標數據了。FETCH 指出要檢索哪些行,從何處檢索它們以及將它們放於何處(如變量名)。
使用 Oracle 語法從遊標中檢索一行:
DECLARE TYPE CustCursor IS REF CURSOR RETURN Customers%ROWTYPE
DECLARE CustRecord Customers%ROWTYPE;
BEGIN
OPEN CustCursor;
FETCH CustCursor INTO CustRecord;
CLOSE CustCursor;
END;
複製代碼
CLOSE 語句用來關閉遊標。一旦遊標關閉,若是再也不次打開,將不能使 用。第二次使用它時不須要再聲明,只需用 OPEN 打開它便可。
CLOSE CustCursor
複製代碼
約束(constraint):管理如何插入或處理數據庫數據的規則。
主鍵是一種特殊的約束,用來 一組列)中的值是惟一的,並且永不改動。換句話說,表中的一列(或 多個列)的值惟一標識表中的每一行。這方便了直接或交互地處理表中的行。沒有主鍵,要安全地 UPDATE 或 DELETE 特定行而不影響其餘行會 很是困難。
表中任意列只要知足如下條件,均可以用於主鍵。
一種定義主鍵的方法是建立它:
CREATE TABLE Vendors
(
vend_id CHAR(10) NOT NULL PRIMARY KEY,
vend_name CHAR(50) NOT NULL,
vend_address CHAR(50) NULL,
vend_city CHAR(50) NULL,
vend_state CHAR(5) NULL,
vend_zip CHAR(10) NULL,
vend_country CHAR(50) NULL
);
複製代碼
另外一種方法:
ALTER TABLE Vendors
ADD CONSTRAINT PRIMARY KEY (vend_id);
複製代碼
外鍵是表中的一列,其值必須列在另外一表的主鍵中。外鍵是保證引用完 整性的極其重要部分。
定義外鍵的方法:
CREATE TABLE Orders
(
order_num INTEGER NOT NULL PRIMARY KEY,
order_date DATETIME NOT NULL,
cust_id CHAR(10) NOT NULL REFERENCES Customers(cust_id)
);
複製代碼
也能夠用 CONSTRAINT 來完成:
ALTER TABLE Orders
ADD CONSTRAINT
FOREIGN KEY (cust_id) REFERENCES Customers (cust_id)
複製代碼
外鍵有助防止意外刪除:除幫助保證引用完整性外,外鍵還有另外一個重要做用。在定義外鍵後,DBMS 不容許刪除在另外一個表中具備關聯行的行。
惟一約束用來保證一列(或一組列)中的數據是惟一的。它們相似於主 鍵,但存在如下重要區別。
惟一約束的語法相似於其餘約束的語法。惟一約束既能夠用 UNIQUE 關 鍵字在表定義中定義,也能夠用單獨的 CONSTRAINT 定義。
檢查約束用來保證一列(或一組列)中的數據知足一組指定的條件。檢 查約束的常見用途有如下幾點:
檢查 約束在數據類型內又作了進一步的限制,這些限制極其重要,能夠確保插 入數據庫的數據正是你想要的數據。不須要依賴於客戶端應用程序或用戶 來保證正確獲取它,DBMS 自己將會拒絕任何無效的數據。
施加檢查約束:
CREATE TABLE OrderItems
(
order_num INTEGER NOT NULL,
order_item INTEGER NOT NULL,
prod_id CHAR(10) NOT NULL,
quantity INTEGER NOT NULL CHECK (quantity > 0),
item_price MONEY NOT NULL
);
複製代碼
檢查名爲 gender 的列只包含 M 或 F,可編寫以下的 ALTER TABLE 語句:
ADD CONSTRAINT CHECK (gender LIKE '[MF]')
複製代碼
索引用來排序數據以加快搜索和排序操做的速度。想像一本書後的索引 (如本書後的索引),能夠幫助你理解數據庫的索引。
假如要找出本書中全部的「數據類型」這個詞,簡單的辦法是從第 1 頁 開始,瀏覽每一行。雖然這樣作能夠完成任務,但顯然不是一種好的辦法。瀏覽少數幾頁文字可能還行,但以這種方式瀏覽整部書就不可行了。 隨着要搜索的頁數不斷增長,找出所需詞彙的時間也會增長。
這就是書籍要有索引的緣由。索引按字母順序列出詞彙及其在書中的位 置。爲了搜索「數據類型」一詞,可在索引中找出該詞,肯定它出如今 哪些頁中。而後再翻到這些頁,找出「數據類型」一詞。
使索引有用的因素是什麼?很簡單,就是恰當的排序。找出書中詞彙的 困難不在於必須進行多少搜索,而在於書的內容沒有按詞彙排序。若是 書的內容像字典同樣排序,則索引沒有必要(所以字典就沒有索引)。
數據庫索引的做用也同樣。主鍵數據老是排序的,這是 DBMS 的工做。 所以,按主鍵檢索特定行老是一種快速有效的操做。
可是,搜索其餘列中的值一般效率不高。例如,若是想搜索住在某個州的客戶,怎麼辦?由於表數據並未按州排序,DBMS 必須讀出表中全部行(從第一行開始),看其是否匹配。這就像要從沒有索引的書中找出詞彙同樣。
解決方法是使用索引。能夠在一個或多個列上定義索引,使 DBMS 保存 其內容的一個排過序的列表。在定義了索引後,DBMS 以使用書的索引相似的方法使用它。DBMS 搜索排過序的索引,找出匹配的位置,而後檢索這些行。
在開始建立索引前,應該記住如下內容:
沒有嚴格的規則要求什麼應該索引,什麼時候索引。大多數 DBMS 提供了可 用來肯定索引效率的實用程序,應該常用這些實用程序。
索引用 CREATE INDEX 語句建立:
CREATE INDEX prod_name_ind
ON Products (prod_name);
複製代碼
索引必須惟一命名。
觸發器是特殊的存儲過程,它在特定的數據庫活動發生時自動執行。觸發 器能夠與特定表上的 INSERT、UPDATE 和 DELETE 操做(或組合)相關聯。
與存儲過程不同(存儲過程只是簡單的存儲 SQL 語句),觸發器與單個的表相關聯。與 Orders 表上的 INSERT 操做相關聯的觸發器只在 Orders 表中插入行時執行。 相似地, Customers 表上的 INSERT 和 UPDATE 操做的觸發器只在 Customers 表上出現這些操做時執行。
觸發器內的代碼具備如下數據的訪問權:
下面是觸發器的一些常見用途:
不一樣 DBMS 的觸發器建立語法差別很大,更詳細的信息請參閱相應的文檔。
Oracle 版本:
CREATE TRIGGER customer_state
AFTER INSERT OR UPDATE
FOR EACH ROW
BEGIN
UPDATE Customers
SET cust_state = Upper(cust_state)
WHERE Customers.cust_id = :OLD.cust_id
END;
複製代碼
對於組織來講,沒有什麼比它的數據更重要了,所以應該保護這些數據, 使其不被偷盜或任意瀏覽。固然,數據也必須容許須要訪問它的用戶訪 問,所以大多數 DBMS 都給管理員提供了管理機制,利用管理機制授予 或限制對數據的訪問。
任何安全系統的基礎都是用戶受權和身份確認。這是一種處理,經過這 種處理對用戶進行確認,保證他是有權用戶,容許執行他要執行的操做。 有的 DBMS 爲此結合使用了操做系統的安全措施,而有的維護本身的用戶及密碼列表,還有一些結合使用外部目錄服務服務器。
通常說來,須要保護的操做有: