官术网_书友最值得收藏!

Codd基于對關系模型的定義,他提出了一種叫作DSL/Alpha的語言,用于操作關系數據表中的數據。在Codd的論文發表后不久,IBM委托一個小組根據Codd的想法建立一個原型。這個小組創建了DSL/Alpha的簡化版本SQUARE。經過對SQUARE的改進,產生了SEQUEL語言,最終該語言被命名為SQL。盡管SQL最初是用于操作關系型數據庫中的數據,但如今已經演變為一種可以處理各種數據庫技術的語言(正如你將在本書結尾看到的)。

SQL現在已有40多年的歷史,其間經歷了很大的變化。20世紀80年代中期,美國國家標準協會(American National Standards Institute,ANSI)開始制定SQL語言的第一個標準,該標準最終于1986年發布。隨后經過改進,陸續在1989年、1992年、1999年、2003年、2006年、2008年、2011年、2016年發布了新版本。在改良核心語言的同時,SQL語言中還添加了一些新特性,引入了面向對象功能等。之后的標準側重于相關技術的集成,比如可擴展標記語言(XML)和JavaScript對象表示法(JSON)。

SQL與關系模型相輔相成,因為SQL查詢的結果就是數據表(在該上下文中,也叫作結果集)。所以,在關系型數據庫中,新的永久性數據表可以通過存儲查詢的結果集來創建。同樣,查詢可以使用永久性數據表和其他查詢的結果集作為輸出(我們會在第9章討論相關細節)。

最后強調一點:SQL并不是某種縮寫[盡管很多人堅持認為它表示“Structured Query Language”(結構化查詢語言)]。在提及該語言時,可以使用獨立的字母(S.Q.L)或使用“sequel”。

SQL語言被劃分為若干部分:我們在本書中研究的部分包括SQL模式語句(SQL schema statement),用于定義存儲在數據庫中的數據結構;SQL數據語句(SQL data statement),用于操作之前使用SQL模式語句定義的數據結構;SQL事務語句(SQL transaction statement),用于啟動、結束、回滾事務(相關概念會在第12章介紹)。例如,要想在數據庫中創建新表,可以使用SQL模式語句create table,要在新表中填充數據,則需要使用SQL數據語句insert。

下面給出創建數據表corporation的SQL模式語句:

CREATE TABLE corporation
 (corp_id SMALLINT,
  name VARCHAR(30),
  CONSTRAINT pk_corporation PRIMARY KEY (corp_id)
 );

該語句創建出一個包含兩列數據(corp_id和name)的表,其中corp_id列作為該表的主鍵。這個語句的具體細節(比如MySQL可用的數據類型)我們留待在第2章中仔細研究。接下來的SQL數據語句向corporation表中插入了一行關于Acme Paper Corporation的數據:

INSERT INTO corporation (corp_id, name)
VALUES (27, 'Acme Paper Corporation');

該語句向corporation表中添加了一行數據,其中corp_id列的值為27,name列的值為Acme Paper Corporation。

最后是一個簡單的select語句,檢索剛才創建好的數據:

mysql< SELECT name
    -> FROM corporation
    -> WHERE corp_id = 27;
+------------------------+
| name                   |
+------------------------+
| Acme Paper Corporation |
+------------------------+

通過SQL模式語句所創建的所有數據庫元素都被存儲在一個名為“數據字典”(data dictionary)的特殊表集合內。這些關于數據庫的數據被稱為“元數據”,我們將在第15章介紹。與用戶創建的數據表一樣,數據字典表也可以通過select語句查詢,從而允許在運行時查看數據庫中當前的數據結構。例如,用戶需要創建展示上月新增賬戶的報表,那么既可以在Account表中硬編碼事先已經知道的列名,也可以通過查詢數據字典確定當前有哪些列,然后每次動態地生成報表。

本書大部分篇幅將聚焦于SQL語言中與數據相關的部分,包括select、update、insert、delete命令。SQL模式語句將在第2章中說明,這將引導你完成一些簡單的數據表的設計和創建。一般來說,除了語法,對于SQL模式語句無須進行太多的討論,而SQL數據語句,盡管數量寥寥,但包含了大量值得仔細研究的地方。因此,雖然我會介紹不少SQL模式語句,但本書的大多數章節還是把重點放在SQL數據語句上。

如果你有編程經驗,肯定已經習慣了定義變量和數據結構、使用條件邏輯(if-then-else)和循環結構(do while...end)、把代碼分解為可復用的小片段(對象、函數、過程)。代碼經過編譯后執行,其執行結果精確地(其實,并非總是精確地)符合預期。無論是使用Java、Python、Scala或其他過程化語言,你都可以完全控制程序的行為。

圖片 19{}過程化語言定義了所預期的結果以及生成該結果的實現機制或過程。非過程化語言同樣定義了所預期的結果,但是生成結果的過程則留給外部代理來實現。

對于SQL,你需要放棄部分已經習慣的控制權,因為SQL語句只定義了必要的輸入和輸出,至于如何執行語句,則由名為優化器(optimizer)的數據庫引擎組件來處理。優化器的工作是檢查SQL語句,考慮數據表的配置以及可用的索引,并決定最有效的執行路徑(好吧,也未必總是最有效的)。大多數數據庫引擎都允許你通過指定優化器提示(optimizer hint)來影響優化器的決策,比如建議使用特定的索引等,但大多數SQL用戶從來不需要深入到該復雜層面,把這種事交給數據庫管理員或性能調優專家來處理就行了。

因此,單憑SQL無法編寫完整的應用程序,除非你只是編寫簡單的腳本來處理某些數據,否則需要將SQL與編程語言集成起來。一些數據庫廠商已經為用戶考慮了這些,比如Oracle的PL/SQL語言、MySQL的存儲過程語言以及Microsoft的Transact-SQL語言。在這些語言中,SQL數據語句是該語言語法的一部分,允許無縫地將數據庫查詢與過程化語句集成到一起。如果你使用的是Java或Python這種非數據庫特定語言,則需要使用工具集/API才能在代碼中執行SQL語句。有些工具集由數據庫廠商提供,有些則由第三方廠商或開源代碼提供者所創建。表1-2展示了將SQL集成到特定語言的部分可用選擇。

表1-2 SQL集成工具集

如果僅僅需要交互式執行SQL命令,所有的數據庫廠商都提供了至少一種簡單的命令行工具,用于向數據庫引擎提交SQL命令并檢查執行結果。大多數廠商還提供了圖形化的工具,其中包含一個顯示SQL命令的窗口以及一個顯示SQL命令執行結果的窗口。此外,SQuirrel等第三方工具可以通過JDBC連接到很多不同的數據庫服務器。因為本書中的示例都是在MySQL數據庫中執行的,所以我選擇使用MySQL安裝自帶的命令行工具來運行示例和格式化運行結果。

之前答應過要展示一個能夠返回George Blake的支票賬戶所有交易的SQL語句,下面就是這些SQL語句:

SELECT t.txn_id, t.txn_type_cd, t.txn_date, t.amount
FROM individual i
  INNER JOIN account a ON i.cust_id = a.cust_id
  INNER JOIN product p ON p.product_cd = a.product_cd
  INNER JOIN transaction t ON t.account_id = a.account_id
WHERE i.fname = 'George' AND i.lname = 'Blake'
  AND p.name = 'checking account';
+--------+-------------+---------------------+--------+
| txn_id | txn_type_cd | txn_date            | amount |
+--------+-------------+---------------------+--------+
|     11 | DBT         | 2008-01-05 00:00:00 | 100.00 |
+--------+-------------+---------------------+--------+
1 row in set (0.00 sec)

現在先不涉及過多的細節,該查詢查找滿足兩個條件的行,即individual表中姓名為George Blake的行和product表中的name列為checking的行,并通過account表將兩者關聯起來,然后分4列返回transaction表中提交到該賬戶的所有交易信息。如果你恰好知道George Blake的account_id為8,product_cd為'CHK',就可以簡單地根據客戶ID在account表中找到George Blake的支票賬戶,并使用賬戶ID找出相應的交易:

SELECT t.txn_id, t.txn_type_cd, t.txn_date, t.amount
FROM account a
  INNER JOIN transaction t ON t.account_id = a.account_id
WHERE a.cust_id = 8 AND a.product_cd = 'CHK';

在隨后的章節中,我會逐一介紹以上查詢中涉及的所有概念(而且遠不止這些),但這里僅展示一下其基本結構。

上述查詢包含三種不同的子句:select、from和where。幾乎所有查詢至少都會包含這三種子句,盡管還有更多子句可用于實現更具體的目標。它們的用途如下所示:

SELECT /* 一個或多個東西 */ ...
FROM   /* 一處或多處 */ ...
WHERE  /* 一個或多個條件 */ ...

圖片 19{}大多數SQL實現將位于“/”和“/”之間的文本視為注釋。
 

在構建查詢時,通常首先要確定需要哪些數據表,接著將其加入from子句。然后,向where子句加入條件,將數據表中不需要的數據過濾掉。最后,確定要檢索數據表中的哪些列并將其加入select子句。下面這個簡單的示例展示了如何查找姓氏為“Smith”的所有客戶:

SELECT cust_id, fname
FROM individual
WHERE lname = 'Smith';

該查詢搜索individual表,在其中找出lname列匹配字符串'Smith'的所有行,并返回這些行的列cust_id和fname。

除了查詢數據庫,很可能還需要在數據庫中插入和修改數據。下面這個簡單的例子,展示了如何在product表中插入新行:

INSERT INTO product (product_cd, name)
VALUES ('CD', 'Certificate of Depysit')

糟糕,這里把“Deposit”拼錯了。無妨,可以使用update語句來解決:

UPDATE product
SET name = 'Certificate of Deposit'
WHERE product_cd = 'CD';

注意,與select語句一樣,update語句也包含了where 子句。原因在于update語句必須標識出要修改的行,在本例中,只需要指定product_cd列與字符串'CD'相匹配的那些行。因為product_cd列是product表的主鍵,所以update語句只會修改一行(或者一行都不修改,如果數據表中不存在該值的話)。不管什么時候執行SQL數據語句,都會接收到來自數據庫引擎的反饋,說明有多少行受到該語句的影響。如果使用交互式工具(比如之前提到的命令行工具),那么會接收到來自下列語句的反饋信息:

●select語句返回的行數;

●insert語句創建的行數;

●update語句修改的行數;

●delete語句刪除的行數。

如果你使用了過程化語言以及之前提到的某種工具集,當你執行SQL數據語句之后,可以使用工具集提供的調用來獲取語句的執行結果。一般而言,最好是檢查一下執行結果,以免語句執行后出現意想不到的結果(比如忘了在delete語句中加入where子句,這會把整個數據表的行全部清空?。?/p>

主站蜘蛛池模板: 兴安县| 万载县| 克拉玛依市| 永川市| 沾化县| 嘉峪关市| 新巴尔虎右旗| 鹿邑县| 丹寨县| 华池县| 前郭尔| 印江| 河津市| 赣榆县| 泗洪县| 满洲里市| 乐昌市| 大关县| 新龙县| 越西县| 观塘区| 桑植县| 嘉兴市| 博湖县| 夏河县| 方城县| 天津市| 大荔县| 天峨县| 吴江市| 兴业县| 桃园县| 福建省| 合江县| 当涂县| 黄陵县| 房产| 霍邱县| 蒙山县| 象州县| 凤庆县|