PSQL 簡介

Juanito FatasThinking about what to do.

先建立一個資料庫供本文練習用:

$ createdb play

連進 play 資料庫:

$ psql play
psql (9.3.1)
Type "help" for help.

play=#

PostgreSQL 的資料庫透過 psql 來操作。

$ 是 bash 的提示符,psql 的提示符則是 [DATABASE_NAME]=#

SQL 不分大小寫。

輸入 help

play=# help
You are using psql, the command-line interface to PostgreSQL.
Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit
psql 指令 用途
\h 顯示 “SQL” 指令的幫助資訊
\? 顯示 “psql” 指令的幫助資訊
\q 離開 psql。

psql 的指令由 \ 開始。其它像是 CREATEINSERTSELECT 等,是常見的 SQL 指令,不是 psql 指令。

play=# \h create table
Command:     CREATE TABLE
Description: define a new table
Syntax:
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [
  { column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
    | table_constraint
    | LIKE source_table [ like_option ... ] }
    [, ... ]
] )
[ INHERITS ( parent_table [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]
...
略

play=# \d
No relations found.

在 PostgreSQL 裡,relations 就是資料表(Table)。

play=# create table authors ( name varchar(255) );
CREATE TABLE

資料表命名為複數形式 authors

行尾的 ; 很重要,只有看到 ; 才會執行 SQL。

psql 的指令則不需要 ;

play=# \d
        List of relations
 Schema |  Name   | Type  | Owner
--------+---------+-------+-------
 public | authors | table | Mac
(1 row)

按上可以找到之前輸入過的指令。

\d 也可以描述特定的資料表:

play=# \d authors
           Table "public.authors"
 Column |          Type          | Modifiers
--------+------------------------+-----------
 name   | character varying(255) |

play=# insert into authors(name) values('Matz');
INSERT 0 1
play=# insert into authors(name) values('村上春樹');
INSERT 0 1
play=# insert into authors(name) values('Juanito');
INSERT 0 1

剛剛插入了三筆資料,現在選出來看看:

play=# select * from authors;
   name
----------
 Matz
 村上春樹
 Juanito
(3 rows)

每筆資料在資料表當中是一“列”(row)。

大陸的行與列與台灣顛倒,閱讀簡體文章需要注意。

輸入很長的 SQL 語句時,在自己擅長的編輯器裡會方便許多。

play=# \e

便會打開編輯器,預設會打開 Vim。

首先離開 psql:

play=# \q

把編輯器設定成 Sublime Text,設定全域變數 $EDITOR

$ export EDITOR="subl -w"

回到 psql 輸入 \e 便會打開 Sublime Text。

在編輯器輸入完指令,關掉編輯器,便會執行剛剛輸入的指令。

再次回到 play 資料庫:

$ psql play
play=#

再次把 authors 表叫出來看看:

play=# \d authors
           Table "public.authors"
 Column |          Type          | Modifiers
--------+------------------------+-----------
 name   | character varying(255) |

有沒有發現那裡怪怪的?少了主鍵(Primary key)!

讓我們補上主鍵:

play=# alter table authors
play-# add column author_id serial primary key;
ALTER TABLE

注意第一行沒有 ;,第二行的提示符號變成了 play-# 已供識別。

看看上條指令是否成功:

play=# \d authors
                                      Table "public.authors"
  Column   |          Type          |                          Modifiers
-----------+------------------------+-------------------------------------------------------------
 name      | character varying(255) |
 author_id | integer                | not null default nextval('authors_author_id_seq'::regclass)
Indexes:
    "authors_pkey" PRIMARY KEY, btree (author_id)

authors 都選出來看看:

play=# select * from authors;
   name   | author_id
----------+-----------
 Matz     |         1
 村上春樹 |         2
 Juanito  |         3
(3 rows)

注意到 PostgreSQL 自動幫我們把主鍵的值按順序填好了呢,不錯不錯。

為了要示範連接資料表,讓我們再建立另一張資料表:

play=# create table books (
play(#   book_id serial primary key,
play(#   title text,
play(#
play(#   author_id integer references authors(author_id)
play(# );
CREATE TABLE

author_id 是外鍵(Foreign key)。

外鍵是「指向另個表格主鍵的欄位」。以上例來解釋就是:「這本書的作者編號」。

這時候再輸入 \d 看看:

play=# \d
                 List of relations
 Schema |         Name          |   Type   | Owner
--------+-----------------------+----------+-------
 public | authors               | table    | Mac
 public | authors_author_id_seq | sequence | Mac
 public | books                 | table    | Mac
 public | books_book_id_seq     | sequence | Mac
(4 rows)

會發現到多了兩個 sequence,這是用來自動遞增主鍵之用。

讓我們先為每位作者新增著作:

play=# insert into books(title, author_id) values('Programming Ruby 4.2', 1);
INSERT 0 1
play=# insert into books(title, author_id) values('該邊的卡夫卡', 2);
INSERT 0 1
play=# insert into books(title, author_id) values('Rails 指南', 3);
INSERT 0 1

接下來看看如何使用 JOIN,在做 JOIN 之前,先看看要 JOIN 的兩張表,長什麼樣子:

play=# select * from authors;
   name   | author_id
----------+-----------
 Matz     |         1
 村上春樹  |         2
 Juanito  |         3
(3 rows)

play=# select * from books;
 book_id |        title         | author_id
---------+----------------------+-----------
       1 | Programming Ruby 4.2 |         1
       2 | 該邊的卡夫卡          |         2
       3 | Rails 指南           |         3
(3 rows)

現在讓我們用 JOIN 選出書名與作者名稱吧:

play=# select books.title, authors.name from books join authors on books.author_id = authors.author_id;
        title         |   name
----------------------+----------
 Programming Ruby 4.2 | Matz
 該邊的卡夫卡          | 村上春樹
 Rails 指南           | Juanito
(3 rows)

使用 explainexplain analyze

explain select * from users where id = 1
explain analyze select * from users where id = 1

explain: 不會執行查詢,會告訴你 Postgres 會怎樣執行這個查詢。
explain analyze: 會執行查詢,會告訴你 Postgres 執行了這個查詢後的許多資訊。

根據上述輸出,常見優化就是加 index。

つづく。