PostgreSQL(一)教程 -----SQL語言

1、概念java

      PostgreSQL是一種關係型數據庫管理系統 (RDBMS)。這意味着它是一種用於管理存儲在關係中的數據的系統。關係其實是的數學術語。 今天,把數據存儲在表裏的概念已經快成了固有的常識了, 可是還有其它的一些方法用於組織數據庫。在類 Unix 操做系統上的文件和目錄就造成了一種層次數據庫的例子。 更現代的發展是面向對象數據庫。sql

每一個表都是一個命名的集合。一個給定表的每一行由同一組的命名組成,並且每一列都有一個特定的數據類型。雖然列在每行裏的順序是固定的, 但必定要記住 SQL 並不對行在表中的順序作任何保證(但你能夠爲了顯示的目的對它們進行顯式地排序)。數據庫

表被分組成數據庫,一個由單個PostgreSQL服務器實例管理的數據庫集合組成一個數據庫集簇後端

2、建立一個新表服務器

     你能夠經過指定表的名字和全部列的名字及其類型來建立表∶函數

CREATE TABLE weather (
    city            varchar(80),
    temp_lo         int,           -- 最低溫度
    temp_hi         int,           -- 最高溫度
    prcp            real,          -- 溼度
    date            date
);

你能夠在psql輸入這些命令以及換行符。psql能夠識別該命令直到分號才結束。
你能夠在 SQL 命令中自由使用空白(即空格、製表符和換行符)。 這就意味着你能夠用和上面不一樣的對齊方式鍵入命令,或者將命令所有放在一行中。兩個劃線("--")引入註釋。
任何跟在它後面直到行尾的東西都會被忽略。SQL 是對關鍵字和標識符大小寫不敏感的語言,只有在標識符用雙引號包圍時才能保留它們的大小寫(上例沒有這麼作)。
varchar(80)指定了一個能夠存儲最長 80 個字符的任意字符串的數據類型。int是普通的整數類型。real是一種用於存儲單精度浮點數的類型。date類型應該能夠自解釋(沒錯,類型爲date的列名字也是date。 這麼作可能比較方便或者容易讓人混淆 — 你本身選擇)。
PostgreSQL支持標準的SQL類型intsmallintrealdouble precisionchar(N)varchar(N)datetimetimestampinterval,還支持其餘的通用功能的類型和豐富的幾何類型。PostgreSQL中能夠定製任意數量的用戶定義數據類型。於是類型名並非語法關鍵字,除了SQL標準要求支持的特例外。

第二個例子將保存城市和它們相關的地理位置:
CREATE TABLE cities (
    name            varchar(80),
    location        point
);
類型point就是一種PostgreSQL特有數據類型的例子。
最後,咱們還要提到若是你再也不須要某個表,或者你想以不一樣的形式重建它,那麼你能夠用下面的命令刪除它:
DROP TABLE tablename;

3、在表中 增長行
INSERT語句用於向表中添加行:
INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27');

  

請注意全部數據類型都使用了至關明瞭的輸入格式。那些不是簡單數字值的常量一般必需用單引號(')包圍,就象在例子裏同樣。date類型實際上對可接收的格式至關靈活,不過在本教程裏,咱們應該堅持使用這種清晰的格式。優化

point類型要求一個座標對做爲輸入,以下:spa

INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)');

  到目前爲止使用的語法要求你記住列的順序。一個可選的語法容許你明確地列出列:操作系統

INSERT INTO weather (city, temp_lo, temp_hi, prcp, date)
    VALUES ('San Francisco', 43, 57, 0.0, '1994-11-29');

  若是你須要,你能夠用另一個順序列出列或者是忽略某些列, 好比說,咱們不知道降水量:3d

INSERT INTO weather (date, city, temp_hi, temp_lo)
    VALUES ('1994-11-29', 'Hayward', 54, 37);

  

許多開發人員認爲明確列出列要比依賴隱含的順序是更好的風格。

請輸入上面顯示的全部命令,這樣你在隨後的各節中才有可用的數據。

你還可使用COPY從文本文件中裝載大量數據。這種方式一般更快,由於COPY命令就是爲這類應用優化的, 只是比 INSERT少一些靈活性。好比:

COPY weather FROM '/home/user/weather.txt';

  這裏源文件的文件名必須在運行後端進程的機器上是可用的, 而不是在客戶端上,由於後端進程將直接讀取該文件。

 

4、查詢一個表

要從一個表中檢索數據就是查詢這個表。SQLSELECT語句就是作這個用途的。 該語句分爲選擇列表(列出要返回的列)、表列表(列出從中檢索數據的表)以及可選的條件(指定任意的限制)。好比,要檢索表weather的全部行,鍵入:

SELECT * FROM weather;

  這裏*"全部列"的縮寫。所以相同的結果應該這樣得到:

SELECT city, temp_lo, temp_hi, prcp, date FROM weather;

  

你能夠在選擇列表中寫任意表達式,而不只僅是列的列表。好比,你能夠:

SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather;

  

請注意這裏的AS子句是如何給輸出列從新命名的(AS子句是可選的)。

一個查詢可使用WHERE子句"修飾",它指定須要哪些行。WHERE子句包含一個布爾(真值)表達式,只有那些使布爾表達式爲真的行纔會被返回。在條件中可使用經常使用的布爾操做符(ANDORNOT)。 好比,下面的查詢檢索舊金山的下雨天的天氣:

SELECT * FROM weather
    WHERE city = 'San Francisco' AND prcp > 0.0;

  你能夠要求返回的查詢結果是排好序的:

SELECT * FROM weather
    ORDER BY city;

  

在這個例子裏,排序的順序並未徹底被指定,所以你可能看到屬於舊金山的行被隨機地排序。可是若是你使用下面的語句,那麼就老是會獲得上面的結果:

SELECT * FROM weather
    ORDER BY city, temp_lo;

  你能夠要求在查詢的結果中消除重複的行:

SELECT DISTINCT city
    FROM weather;

  再次聲明,結果行的順序可能變化。你能夠組合使用DISTINCTORDER BY來保證獲取一致的結果

SELECT DISTINCT city
    FROM weather
    ORDER BY city;

  

 

5、在表之間的鏈接

     到目前爲止,咱們的查詢一次只訪問一個表。查詢能夠一次訪問多個表,或者用這種方式訪問一個表而同時處理該表的多個行。 一個同時訪問同一個或者不一樣表的多個行的查詢叫鏈接查詢。舉例來講,好比你想列出全部天氣記錄以及相關的城市位置。要實現這個目標,咱們須要拿 weather表每行的city列和cities表全部行的name列進行比較, 並選取那些在該值上相匹配的行對。

SELECT *
    FROM weather, cities
    WHERE city = name;

  

觀察結果集的兩個方面:

  • 沒有城市Hayward的結果行。這是由於在cities表裏面沒有Hayward的匹配行,因此鏈接忽略 weather表裏的不匹配行。咱們稍後將看到如何修補它。

  • 有兩個列包含城市名字。這是正確的, 由於weathercities表的列被串接在一塊兒。不過,實際上咱們不想要這些, 所以你將可能但願明確列出輸出列而不是使用*

    SELECT city, temp_lo, temp_hi, prcp, date, location
        FROM weather, cities
        WHERE city = name;
    

      

    這個語法並不象上文的那個那麼經常使用,咱們在這裏寫出來是爲了讓你更容易瞭解後面的主題。

    如今咱們將看看如何能把Hayward記錄找回來。咱們想讓查詢乾的事是掃描weather表, 而且對每一行都找出匹配的cities錶行。若是咱們沒有找到匹配的行,那麼咱們須要一些"空值"代替cities表的列。 這種類型的查詢叫外鏈接 (咱們在此以前看到的鏈接都是內鏈接)。這樣的命令看起來象這樣:

    SELECT *
        FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name);
    
         city      | temp_lo | temp_hi | prcp |    date    |     name      | location
    ---------------+---------+---------+------+------------+---------------+-----------
     Hayward       |      37 |      54 |      | 1994-11-29 |               |
     San Francisco |      46 |      50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
     San Francisco |      43 |      57 |    0 | 1994-11-29 | San Francisco | (-194,53)
    (3 rows)
    

      這個查詢是一個左外鏈接, 由於在鏈接操做符左部的表中的行在輸出中至少要出現一次, 而在右部的表的行只有在能找到匹配的左部錶行是才被輸出。 若是輸出的左部表的行沒有對應匹配的右部表的行,那麼右部錶行的列將填充空值(null)。

還有右外鏈接和全外鏈接。
咱們也能夠把一個表和本身鏈接起來。這叫作自鏈接。 好比,假設咱們想找出那些在其它天氣記錄的溫度範圍以外的天氣記錄。這樣咱們就須要拿 weather表裏每行的temp_lotemp_hi列與weather表裏其它行的temp_lotemp_hi列進行比較。咱們能夠用下面的查詢實現這個目標:
SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high,
    W2.city, W2.temp_lo AS low, W2.temp_hi AS high
    FROM weather W1, weather W2
    WHERE W1.temp_lo < W2.temp_lo
    AND W1.temp_hi > W2.temp_hi;

     city      | low | high |     city      | low | high
---------------+-----+------+---------------+-----+------
 San Francisco |  43 |   57 | San Francisco |  46 |   50
 Hayward       |  37 |   54 | San Francisco |  46 |   50
(2 rows)

  在這裏咱們把weather表從新標記爲W1W2以區分鏈接的左部和右部。你還能夠用這樣的別名在其它查詢裏節約一些敲鍵,好比:

SELECT *
    FROM weather w, cities c
    WHERE w.city = c.name;

  

6、彙集函數

和大多數其它關係數據庫產品同樣,PostgreSQL支持彙集函數。 一個彙集函數從多個輸入行中計算出一個結果。 好比,咱們有在一個行集合上計算count(計數)、sum(和)、avg(均值)、max(最大值)和min(最小值)的函數。

好比,咱們能夠用下面的語句找出全部記錄中最低溫度中的最高溫度:

SELECT max(temp_lo) FROM weather;
 max
-----
  46
(1 row)

  若是咱們想知道該讀數發生在哪一個城市,咱們能夠用:

SELECT city FROM weather WHERE temp_lo = max(temp_lo);     錯誤

  不過這個方法不能運轉,由於彙集max不能被用於WHERE子句中(存在這個限制是由於WHERE子句決定哪些行能夠被彙集計算包括;所以顯然它必需在彙集函數以前被計算)。 不過,咱們一般均可以用其它方法實現咱們的目的;這裏咱們就可使用子查詢

SELECT city FROM weather
    WHERE temp_lo = (SELECT max(temp_lo) FROM weather);

city
---------------
 San Francisco
(1 row)

  

這樣作是 OK 的,由於子查詢是一次獨立的計算,它獨立於外層的查詢計算出本身的彙集。

彙集一樣也經常使用於和GROUP BY子句組合。好比,咱們能夠獲取每一個城市觀測到的最低溫度的最高值:

SELECT city, max(temp_lo)
    FROM weather
    GROUP BY city;


 city      | max
---------------+-----
 Hayward       |  37
 San Francisco |  46
(2 rows)

  這樣給咱們每一個城市一個輸出。每一個彙集結果都是在匹配該城市的錶行上面計算的。咱們能夠用HAVING 過濾這些被分組的行:

SELECT city, max(temp_lo)
    FROM weather
    GROUP BY city
    HAVING max(temp_lo) < 40;

city   | max
---------+-----
 Hayward |  37
(1 row)

  這樣就只給出那些全部temp_lo值曾都低於 40的城市。最後,若是咱們只關心那些名字以"S"開頭的城市,咱們能夠用:

SELECT city, max(temp_lo)
    FROM weather
    WHERE city LIKE 'S%'
    GROUP BY city
    HAVING max(temp_lo) < 40;

  LIKE操做符進行模式匹配

理解彙集和SQLWHERE以及HAVING子句之間的關係對咱們很是重要。WHEREHAVING的基本區別以下:WHERE在分組和彙集計算以前選取輸入行(所以,它控制哪些行進入彙集計算), 而HAVING在分組和彙集以後選取分組行。所以,WHERE子句不能包含彙集函數; 由於試圖用匯集函數判斷哪些行應輸入給彙集運算是沒有意義的。相反,HAVING子句老是包含彙集函數(嚴格說來,你能夠寫不使用匯集的HAVING子句, 但這樣作不多有用。一樣的條件用在WHERE階段會更有效)。

在前面的例子裏,咱們能夠在WHERE裏應用城市名稱限制,由於它不須要彙集。這樣比放在HAVING裏更加高效,由於能夠避免那些未經過 WHERE檢查的行參與到分組和彙集計算中。

 

7、更新

你能夠用UPDATE命令更新現有的行。假設你發現全部 11 月 28 日之後的溫度讀數都低了兩度,那麼你就能夠用下面的方式改正數據:

UPDATE weather
    SET temp_hi = temp_hi - 2,  temp_lo = temp_lo - 2
    WHERE date > '1994-11-28';

  看看數據的新狀態:

SELECT * FROM weather;

     city      | temp_lo | temp_hi | prcp |    date
---------------+---------+---------+------+------------
 San Francisco |      46 |      50 | 0.25 | 1994-11-27
 San Francisco |      41 |      55 |    0 | 1994-11-29
 Hayward       |      35 |      52 |      | 1994-11-29
(3 rows)

  

8、刪除

數據行能夠用DELETE命令從表中刪除。假設你對Hayward的天氣再也不感興趣,那麼你能夠用下面的方法把那些行從表中刪除:

DELETE FROM weather WHERE city = 'Hayward';

  全部屬於Hayward的天氣記錄都被刪除。

咱們用下面形式的語句的時候必定要當心

DELETE FROM tablename;

  若是沒有一個限制,DELETE將從指定表中刪除全部行,把它清空。作這些以前系統不會請求你確認!

相關文章
相關標籤/搜索