PostgreSQL 全方位指南

PostgreSQL 簡介

基于 C++開發,免費使用、修改、和分發 PostgreSQL,不管是私用、商用、還是學術研究使用。

開始使用

Linux 下的安裝

  • 第一步:安裝
    運行命令:sudo apt-get install postgresql -y

  • 第二步:安全設置
    安裝 postgresql 之后系統會自動創建一個空密碼的 postgres 空密碼用戶,現在為她添加密碼
    sudo passwd postgres

  • 第三步:連接數據庫
    psql postgres

  • 第四步:查看幫助

postgres=# help
You are using psql, the command-line interface to PostgreSQL.
Type:  \copyright for distribution terms
       \h for help with SomethingQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit

Mac 下的安裝

  • 第一步:安裝
    運行命令:brew install postgresql
  • 第二步:添加用戶,創建數據庫
createuser postgres
createdb -U postgres postgres
  • 第三步:建立別名
alias pg.start='pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start'
alias pg.stop='pg_ctl -D /usr/local/var/postgres stop -s -m fast'
  • 第四步:啟動、連接數據庫
pg.start
psql postgres
  • 第五步:查看幫助
postgres=# 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

pgAdmin3

一個設計,維護和管理 Postgres 數據庫用的通用工具。

危險!連接不成功要注意的地方

  • 注意服務器的防火墻規則
  • 修改服務器連接監聽 ( postgersql.conf 配置文件 )
  • 修改連接認真方式 ( pg_hba.conf 配置文件 )

SQL 的組成

SQL

操作數據庫對象

沒有權限怎么辦?

必須使用超級管理員登陸才可以管理數據庫對象,默認的 postgres 可能沒有建立數據庫權限。

權限
用戶

使用 posgres 用戶登陸依然可以看到其他用戶的,找到你的超級用戶且用該賬戶登陸。

使用 pgAdmin 操作

新建操作

數據庫面板

右鍵數據庫,就可以看見新建數據庫選項。

新建面板

在面板上面,填好你要設置的內容,點擊 SQL 選項卡,可以看到如下語句,這樣我們也同樣學習了語句。

CREATE DATABASE apple
  WITH ENCODING='UTF8'
       OWNER="Yugo"
       CONNECTION LIMIT=-1;
COMMENT ON DATABASE apple
  IS '這是我的 Blog 的數據庫';

編輯、刪除操作

基本屬性

這是已經創建好的數據庫的基本屬性(連接數 -1 表示不限制)

編輯

  • Create 腳本 (跟創建的時候 SQL 差不多,不過多了一些默認選項)
  • 屬性 (編輯)
  • 刪除/移除
數據庫名稱

修改了數據庫的基本屬性之后,還是會生成 SQL 語句

ALTER DATABASE apple
  RENAME TO banana;

使用 SQL 語句操作

使用 pgAdmin 練習 SQL

執行任意 SQL

點擊該按鈕,彈出 SQL 編輯窗口

執行 SQL 語句

選擇你寫好的語句,點擊執行按鈕

反饋

執行成功后,將會給你相應的反饋

使用終端進行操作

Yugo=# \c
You are now connected to database "Yugo" as user "Yugo".

\c 查看我當前用戶,和數據庫屬于的用戶

Yugo=# \l
                              List of databases
   Name    | Owner | Encoding |   Collate   |    Ctype    | Access privileges
-----------+-------+----------+-------------+-------------+-------------------
 Yugo      | Yugo  | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |
 banana    | Yugo  | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |
 db_milk   | Yugo  | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |
 postgres  | Yugo  | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 |
 template0 | Yugo  | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/Yugo          +
           |       |          |             |             | Yugo=CTc/Yugo
 template1 | Yugo  | UTF8     | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/Yugo          +
           |       |          |             |             | Yugo=CTc/Yugo
(6 rows)

\l 查看所有數據庫,相當于show databases

Yugo=# \c banana
You are now connected to database "banana" as user "Yugo".

\c banana 切換到banana數據庫 ,相當于use banana

操作表

我們將通過 pgAdmin 的語句生成功能學習

創建表

banana=# create table users
banana-# (
banana(# id int primary key,
banana(# name varchar(25) not null,
banana(# email varchar(60) not null,
banana(# passwd varchar(255) not null);
CREATE TABLE

先創建一個 users

banana=# \d
       List of relations
 Schema | Name  | Type  | Owner
--------+-------+-------+-------
 public | users | table | Yugo
(1 row)

\d 顯示所有的表

banana=# \d users
            Table "public.users"
 Column |          Type          | Modifiers
--------+------------------------+-----------
 id     | integer                | not null
 name   | character varying(25)  | not null
 email  | character varying(60)  | not null
 passwd | character varying(255) | not null
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)

\d users 顯示表 users 的具體內容

腳本

可以看到在 pgAdmin 中已經可以看到表,點擊生成腳本試一試

Create 腳本

CREATE TABLE public.users
(
  id integer NOT NULL,
  name character varying(25) NOT NULL,
  email character varying(60) NOT NULL,
  passwd character varying(255) NOT NULL,
  CONSTRAINT users_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE public.users
  OWNER TO "Yugo";

Select 腳本

SELECT id, name, email, passwd
  FROM public.users;

Insert 腳本

INSERT INTO public.users(
            id, name, email, passwd)
    VALUES (?, ?, ?, ?);

Update 腳本

UPDATE public.users
   SET id=?, name=?, email=?, passwd=?
 WHERE <condition>;

Delete 腳本

DELETE FROM public.users
 WHERE <condition>;
字段

字段也可以顯示 Create 腳本

ALTER TABLE public.users ADD COLUMN name character varying(25);
ALTER TABLE public.users ALTER COLUMN name SET NOT NULL;

索引

新建一個索引 命名為 Index 選擇字段為 id

CREATE INDEX "Index"
    ON public.users (id ASC NULLS LAST)

自己再手寫一些腳本來當做練習

create table student(
    id int primary key,
    name varchar(30) not null,
    age numeric(3) not null,
    classroom numeric(4) not null,
    address varchar(40) not null
);

alter table student rename to person;

alter table person rename id to bh;

alter table person alter column name type varchar(50);

alter table person drop column classroom;

alter table person add column birthday date;

drop table if exists person;

數據類型

復習一下簡單的類型

整數類型

類型 范圍
smallint -32768 - 32767
int -2147483648 - 2147483647

浮點類型

類型 范圍
Real 6位十進制精度
Numeric(m,n) 任意精度類型

來試一試這些類型吧

create table temp(
    x smallint,
    y int,
    z real,
    n numeric(5,3)
)

insert into temp values (2,3,2.55,6.213)

insert into temp values (2,3,2.55,44.412)

insert into temp values (2,3,2.55,44.4125) // 四舍五入

select * from temp;

時間與日期類型

類型名稱 含義 存儲需求 例子
time 只能用于一日內的時間 8 byte 10:02:03
date 只能用于日期 4 byte 1987-04-04
timestamp 日期和時間 8 byte 1987-04-04 10:05:05

動手試一試

create table temp1(
    t time,
    d date,
    tm timestamp
);

insert into temp1 values ('10:04:03','2013-04-23','2031-5-23 10:22:00');

select * from temp1;

字符串類型

類型名稱 說明
char(n)/ character(n) 固定長度字符串,不足補空白
varchar(n)/ character varying(n) 變長字符串,有長度限制
Text 變長字符串,無長度限制

動手吧

create table temp3(
    ch char(10),
    vch varchar(30),
    t text
);

insert into temp3 values('大表哥','大表哥1','大表哥2');

select * from temp3;

select concat('{',ch,'}'),concat('{',vch,'}'),concat('{',t,'}') from temp3;

可以看見ch的后邊補了一些空白

選擇正確的數據類型

主要目的:優化存儲,提高數據庫性能

  • 正確使用整數類型和浮點類型
  • 日期與時間類型
  • Char 與 Varchar 之間的特點與選擇(Char 自動補齊空格,占的空間大,但是在搜索的時候快)

算數運算符

  • 加 +
  • 減 -
  • 乘 ×
  • 除 /
  • 求余、模運算 %

自己跑一跑

select 3+2 , 3-2 , 4*3 , 5/2, 3%2;

比較運算符

  • Least 在倆個或者多個參數時,返回最小值
  • greatest 在倆個或者多個參數時,返回最大值
  • between and 判斷一個值是否落在倆個值之間
  • in 判斷一個值是否是 in 列表中的任意一個值
  • like 通配符匹配

自己跑一跑

select 1=0 , '2'=2, 'b'='b',null=null,null=1;

select 1=0 , '2'=2, 'b'='b',null=null,null=1;

select 'good'<>'god' , 1<>2, 2>1, 4!=4, 2>=1, 1>=1;

select 2 between 1 and 3, 2 between 3 and 5, 3 between 3 and 6  # 閉區間

select 2 in (2,3,4), 2 in (3,4,5), 2 not in (3,4,5);

select 'abc' like 'a%','abc' like '_b_','abc' not like '%d';

邏輯運算符號

  • AND
  • OR
  • NOT

試一試

select not '1', not 'y', not '0', not 'n';

select '1' and 'y' , '1' and '0' , '0' and 'n';

select '1' or 'y' , '1' or '0' , '0' or 'n';

視圖

SQL 里面的視圖,就像一個函數,把一些語句放入這個函數,減少非專業人士的查詢痛苦。

CREATE VIEW myview AS
    SELECT city, temp_lo, temp_hi, prcp, date, location
        FROM weather, cities
        WHERE city = name;

SELECT * FROM myview;

外鍵

保證數據完整

city    varchar(80) references cities(city)

事務

保證里面內容,都完全完成

BEGIN;
UPDATE accounts SET balance = balance - 100.00
    WHERE name = 'Alice';
......
COMMIT;

繼承

關鍵字inherits,繼承人有被繼承的所有屬性,并且查詢也會有點不一樣。

CREATE TABLE cities (
    name            text,
    population      real,
    altitude        int     -- (單位是英尺)
);

CREATE TABLE capitals (     -- (州首府)
    state           char(2)
) INHERITS (cities);
SELECT name, altitude
    FROM cities
    WHERE altitude > 500;

以上找出所有海拔超過 500 英尺的城市的名字, 包括州首府

SELECT name, altitude
    FROM ONLY cities
    WHERE altitude > 500;

以上找出所有不是州首府并且位于海拔大于或等于 500 英尺的城市

深入查詢

語法格式

select
    { * | <字段列表> }
from
    [
        <table_01>,<table_02>...
        [whrere <expression>]
        [group by <字段>]  分組
        [having <expression>]
        [order by <字段>]  排序
        [limit [<offset>,]<row count>
    ]

練習

create table dept (
  d_no int primary key,
  d_name varchar(30),
  d_location varchar(300)
);

insert into dept values (10,'運維部門','美國西雅圖');
insert into dept values (20,'銷售部門','中光廣東');
insert into dept values (30,'測試部門','中國香港');
insert into dept values (40,'集成部門','中國北京');
insert into dept values (50,'財務部門','中國湖北');
insert into dept values (60,'開發部門','中國杭州');

create table employee (
  e_no int primary key, -- 雇員編號
  e_name varchar(30) not null,
  e_gender char(2) not null,
  dept_no int,
  e_job varchar(50) not null,
  e_salary numeric(9,2),
  e_hireDate date,
  constraint fk_tmp_deptno foreign key (dept_no) references dept(d_no)
);

insert into employee values (100,'趙志宇','f',10,'開發工程師',5000,'2010-01-01');
insert into employee values (101,'許啦啦','f',10,'開發工程師',6000,'2013-04-03');
insert into employee values (102,'龍飛機','f',10,'開發經理',8000,'2008-01-01');
insert into employee values (103,'黃飛飛','m',20,'測試工程師',8000,'2009-01-02');
insert into employee values (104,'趙大炮','f',20,'測試工程師',6000,'2012-01-02');
insert into employee values (105,'趙飛機','f',20,'xiaoshou',5000,'2015-01-02');
insert into employee values (106,'吳龜龜','m',30,'xiaoshou',8000,'2014-01-02');
insert into employee values (107,'馮久久','f',30,'xiaoshou',6000,'2002-01-02');
insert into employee values (108,'譚迪迪','f',40,'chaiwu',7000,'2003-01-02');
insert into employee values (109,'廖餅餅','m',40,'chaiwu',6000,'2012-01-02');
insert into employee values (110,'吳大錘','f',null,'實習工程師',2000,'2011-01-02');
insert into employee values (111,'陳大大','f',null,'實習工程師',2000,'2010-01-02');

### select
存取的數據就是用來查的,所以說最基本的操作也是最重要的操作,查詢。

select * from dept;

select * from employee;

select e_no,e_name,e_hireDate from employee;  -- 查詢部分字段

select e.e_no,e.e_name,e.e_hreDate from employee as e; -- 查詢部分字段,且為表設置別名

select e.e_no as a,e.e_name as b,e.e_hreDate as c from employee as e; -- 為字段顯示別名

select e_no,e_name,e_salary from employee where e_salary < 5000;

select e_no,e_name,e_gender from employee where e_gender = 'f';

select 2 in (2,3,4); -- true  , 用于 where 中

select e_no,e_name,dept_no from employee where dept_no in (20,30);

select e_no,e_name,dept_no from employee where dept_no not in (20,30);

select 2 between 2 and 4; -- true , 2 in [2,4] 用于日期方便

select e_no,e_name,dept_no,e_hireDate from employee  where e_hireDate between '2012-03-01' and '2015-01-01';

select 'abc' like 'a%';

select 'abc' like 'a__';

select e_no,e_name,e_job from employee where e_job like '實習%';

select e_no,e_name,dept_no from employee where dept_no is null;

select e_no,e_name,dept_no from employee where dept_no = null; -- error :null 跟任何值都不相等

select e_no,e_name,e_gender,dept_no from employee where e_gender = 'f' and dept_no = 10;

select e_no,e_name,e_gender,dept_no from employee where e_gender = 'f' and dept_no in (10,20);

select e_no,e_name,dept_no from employee where dept_no = 10 or dept_no = 20;

select e_no,e_name,e_salary from employee order by e_salary desc;  -- Desc 降序 asc 升序(默認) null 是最大值

select e_no,e_name,e_salary,e_hireDate from employee order by e_salary asc ,e_hireDate desc;

select e_no,e_name,e_salary,e_hireDate from employee order by e_salary asc ,e_hireDate desc nulls first; -- 這樣 null 顯示在前面 默認是:nulls last

select * from employee limit 5;

select * from employee limit 5 offset 2; -- 從第二條開始 取五條

select e_no,e_name,e_job,d_no,d_name,d_location from employee,dept where dept_no = d_no; -- 空值不會顯示

select e_no,e_name,e_job,d_no,d_name,d_location from employee inner join dept on dept_no = d_no;

select e_no,e_name,e_job,d_no,d_name,d_location from employee left join dept on dept_no = d_no; -- 返回所有,空值無對應照樣顯示空

select e_no,e_name,e_job,d_no,d_name,d_location from employee left outer join dept on dept_no = d_no; -- 左連接與左外連接相等

select e_no,e_name,e_job,d_no,d_name,d_location from employee left outer join dept on dept_no = d_no where dept_no = 10; 

-- join type : inner/left/right

-- 子查詢 : exists 、 in 、標量

select * from employee where exists 
    (select d_no from dept where d_name = '運維部門' and d_no = dept_no);

select * from employee where not exists 
    (select d_no from dept where d_name = '運維部門' and d_no = dept_no);

select * from employee where dept_no in 
    (select d_no from dept where d_name = '運維部門');

-- || 代表字符串拼接

select e_no, e_name, (select d_name || ' ' || d_location 
    from dept where dept_no = d_no) as address from employee;

-- 結果集合并

select e_no,e_name,dept_no,e_salary from employee where dept_no in (10,20)
union all 
select e_no,e_name,dept_no,e_salary from employee where e_salary > 5000;

-- 去掉重復的行
select e_no,e_name,dept_no,e_salary from employee where dept_no in (10,20)
union
select e_no,e_name,dept_no,e_salary from employee where e_salary > 5000;

-- 空值占位
select e_no,e_name,dept_no,e_salary,e_hireDate from employee where dept_no in (10,20)
union
select e_no,e_name,dept_no,e_salary,null from employee where e_salary > 5000;

函數

函數名稱 函數作用
avg() 某列的平均值
count() 某列的行數
max() 某列最大值
min() 某列最小值
sum() 某列之和
length(s) 計算字符串的長度
concate(s1,s2,s3...) 字符串合并函數
ltrim(s)/trim(s)/rtrim(s) 去除空格函數
replace(s,s1,s2) 替換函數
substring(s,n,len) 獲取字串函數
extract(type from d) 獲取日期指定值函數
current_date 當前日期
current_time 當前時間
now() 當前日期時間函數
select e_no,e_name,e_hireDate, extract(year from e_hireDate),
extract(month from e_hireDate), extract(day from e_hireDate) from employee;

自定義函數

讓我們來看看基本語法吧

create function // 聲明創建函數
    add(integer,integer)  // 定義函數名稱,參數類型
returns integer // 定義函數返回值
    as 'select $1 + $2;'  // 定義函數體
language sql    // 用以實現的函數語言的名稱
returns null on null input;  // 定義參數為 Null 的時候的處理情況
create function add(integer,integer) returns integer
  as 'select $1 + $2;'
language sql
returns null on null input;

select add(1,2);

-- or replace 假如數據庫中存在這個函數就替換掉

create or replace function concat_test(integer,varchar,date) returns varchar
  as 'select $1||$2||$3;'
  langugage sql
returns null on null input;

select e_no,e_name,e_hireDate,concat(e_no,e_name,e_hireDate),
concat_test(e_no,e_name,e_hireDate) from employee;

drop function concat_test(integer,varchar,date);

Index 索引

提高數據的查詢速度,加速表與表之間的連接

-- 默認是 B-tree 索引
create index emp_name_index on employee(e_name);
drop index emp_name_index;

視圖

縮短語句的長度利器

create view v_emp_dev as select e_no , e_name ,e_salary , e_hireDate
from employee where dept_no = 10 order by e_salary desc;

select * from v_emp_dev;

drop view v_emp_dev;

其他作者的文章

Rust是Mozilla開發的注重安全、性能和并發性的編程語言
歡迎來 rust-china 社區 http://rust-lang-cn.org/ 逛逛。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375

推薦閱讀更多精彩內容