Postgres 備忘録

公開日: 2022-11-16 更新日: 2024-07-14

psql -h localhost -p 5432 -U postgres -d postgres

Database

テンプレートを指定しない場合は template1 から作られる。

# create db
createdb {DB_NAME} -T template1

# modify db
# (empty)

# list db
psql -l

# switch db
psql -d {DB_NAME}

# drop db
dropdb {DB_NAME}
-- create db
create database {DB_NAME} with template template1

-- modify db
alter database {DB_NAME_OLD} rename to {DB_NAME_NEW}

-- list db
\l

-- switch db
\c {DB_NAME}

-- drop db
drop database {DB_NAME}

Schema

-- create db
create schema {SCHEMA_NAME} 

-- modify db
alter schema {SCHEMA_OLD} rename to {SCHEMA_NEW}

-- list db
\dn

-- drop db
drop schema {SCHEMA_OLD}

Table

-- create table
create table {TABLE_NAME} (column1 integer, column2 varchar(123))

-- modify table
alter table sample_table add col1 varchar(123)

-- list table
\d, \dt

-- drop table
drop table {TABLE_NAME}

Role

データベースクラスタの中で同名ユーザの作成は不可。
データベースクラスタを生成時のOSユーザ名でスーパーユーザが生成される

# create user
createuser {USER_NAME} -l -d -r -s -P
-- create user
create role {USERNAME} with LOGIN PASSWORD 'passwd'

--list user
\du

Domain

制約などを付与した型として使用可能。

create domain {DOMAIN_NAME} as integer check (VALUE < 5)

Database Cluster

postgre はサーバープロセス1つに対して $PGDATA のディレクトリを1つを持つ。
データベースは $PGDATA/base の中にデータベースのOIDが名前となったディレクトリとして格納される。
エンコーディング指定はデータベースとクライアントで異なる事に注意。

EncodingDatabase EncodingClient Encoding
UTF8OKOK
EUC_JPOKOK
SJISNGOK

データベースクラスタは initdb で作る。特にソースコードからビルドした際には initdb で作る必要が有る。このコマンドはホストからのみ実行可能。

useradd -M pst
mkdir /var/dbcl
chown pst:pst /var/dbcl

# -D, --pgdata {DIRECTORY}
# -E, --encoding {ex: utf8, euc_jp}
# -U, --username {USERNAME}
# --no-locale
initdb -D /var/dbcl/ -E utf8 --no-locale -U pst

Admin Tools

pg_ctl

pg_ctl initdb -D|--pgdata {DB_CLUSTER_DIR}

pg_ctl start -D|--pgdata {DB_CLUSTER_DIR} -t {MAX_WAIT_TIME: 60sec}

# -m
#   * smart:     クライアントからの接続が全て切断されるまで待つ
#   * fast:      クライアントからの接続を即遮断. 実行中トランザクションは全てロールバック
#   * immediate: クリーンアップ処理を行わずに停止. クラッシュ相当の状態
# -t
#   待ち時間 (単位: 秒. 既定: 60sec)
# -W
#   待たずに制御を戻す
pg_ctl stop -D|--pgdata {DB_CLUSTER_DIR} -t -m s[mart]|f[ast]|i[mmediate] -W
pg_ctl restart (stop と同一)

# 設定ファイルの再読み込み
pg_ctl reload -D|--pgdata

# 起動状態
pg_ctl status

# プロセス終了
pg_ctl kill TERM|INT|QUIT|HUP {PID}

psql

# 接続
psql -h|--host {HOST} -p|--port {PORT} -U|--user {USER}

Setting file

設定値には型が有る (boolean, integer, floating point, string, enum) boolean には on/off/true/false/yes/no/1/0 が指定可能 一部の設定値には単位を指定可能 (メモリ: kB/MB/GB, 時間: ms/s/min/h/d)

設定反映のタイミング

種別restartpg_ctl reloadsusetset
不可xxxx
起動 (postmaster)oxxx
再読み込み (sighup)ooxx
スーパーユーザのみ (suset)ooox
いつでも (user)oooo

listen_address

サーバー側の ip アドレス (カンマで複数指定可能)。クライアントから宛先未設定の接続を試みられても応答はしない。

  • デフォルト値: localhost
  • 反映: 起動時

port

受け付けるポート番号

  • デフォルト値: 5432
  • 反映: 起動

max_connections

最大同時接続数

  • デフォルト値: 100
  • 反映: 起動

search_path

スキーマ検索パス

  • デフォルト値: “$user”,public
  • 反映: 何時でも誰でも

default_transaction_isolation

トランザクションの分離レベル

  • 型: read uncommitted, read committed, repeatable read, serializable
  • デフォルト値: read committed
  • 反映: 何時でも誰でも

client_encoding

クライアントエンコーディングを指定

  • デフォルト値: SQL_ASCII
  • 反映: 何時でも誰でも

log_destination

ログの保存先。カンマで複数指定可能

  • 型: stderr, csvlog, syslog, eventlog
  • デフォルト値: stderr
  • 反映: reload

出力先

  • stderr: 標準エラー出力
  • csvlog: CSV形式で stderr へ出力。設定の logging_collector を on にする必要有り
  • syslog: syslog へ出力
  • eventlog: イベントログへ出力 (windows 用)

logging_collector

ログをファイルに出力する

  • デフォルト値: off
  • 反映: 起動時

log_directory

ログ出力ディレクトリを指定。絶対パスか $PGDATA からの相対パスで指定。

  • デフォルト値: log ($PGDATA/log)
  • 反映: reload

log_filename

ログファイル名を指定

  • デフォルト値: postgresql-%Y-%m-%d_%H%M%S.log
  • 反映: reload

log_min_message

ログレベルの指定

  • 型: PANIC, FATAL, LOG, ERROR, WARNING etc
  • デフォルト値: WARNING
  • 反映: suset

ログレベル

  • PANIC: 致命的。全てのセッションが強制切断。PostgreSQL 停止。
  • FATAL: 特定のセッションで問題発生。対象セッションのみ切断
  • LOG: 管理者が着目すべき動作ログ
  • ERROR: 特定のトランザクションで問題発生。対象トランザクションのみロールバック
  • WARNING: 想定外の動作に対する警告メッセージ

log_line_prefix

ログの行頭を指定

  • デフォルト値: %m [%p]
  • 反映: reload

使用可能な変数

  • %u: データベースユーザ名
  • %d: データベース名
  • %p: プロセス名
  • %t: タイムスタンプ
  • %m: ミリ秒タイムスタンプ
  • %%: %文字そのもの

SQL (DML)

各構文

-- 基本クエリ
select distinct on ({column_name}) {column_name} [as] {alternative_column_name} ...
from  {table_name}
where {condition}
group by {column_name}
having {column_name}
order by {column_name} {asc|desc}
offset {num}
limit {num}

-- 結合
[inner] join {table_name} on {expression}
[inner] join {table_name} using {column}
natural [inner] join {table_name}
cross join {table_name}
{left|right|full} [outer] join {table_name} on {expression}

-- 条件
where {column_name} [not] in ({value})
where {column_name} = any (query)
where {column_name} between {from} and {to}
where {column_name} is not null
where [not] exists (query)

-- 集合演算
-- 優先度は通常の論理演算と同じ
query
[union|except|intersect][all]
query

-- 更新
insert into {table_name}({column1}, {column2}) values
  ({value1}, {value1}),
  ({value2}, {value2})
;
update {table_name} set {column_name1}={value1}, {column_name2}={value2} where {expression}
delete {table_name} where {expression}

-- 配列
create table array_table (c1 text[], c2 int[])
insert into array_table(c1) values('(1, 2, 3)')
select c1[2] from array_table; -- インデックスは1始まり
select c1[2] from array_table where '1' = any(c1);

-- キャスト
'{table_name}'::regclass
cast({column_name} as integer)
{column_name}::int

データ型

interval で複数形するか否かは自由。

typesizerange
smallint2 byte-3万~3万
integer, int4 byte-2億~2億
bigint8 byteデカい
decimal, numericvariableそこそこ
realvariableそこそこ
double precision8 byte15桁
smallserial2 byte1~3万
serial4 byte1~2億
bigserial8 byteデカい
char(n), character(n)variable空白で埋められた固定長
varchar(n), character varying(n)variable可変長文字列
textvariable可変長文字列
byteavariableバイナリ
timestamp [without time zone]8 byte
timestamp with timezone8 byte
date4 byte
time [without time zone]8 byte
time with time zone12 byte
interval ‘{num} {year|month|day|hour|minute}’16 bytee.g. ‘1 hours 30 minutes’
boolean1 byte{t|‘true’|‘y’|‘yes’|‘on’|‘1’|TRUE}

SQL (DDL)

Table

-- 基本操作
create table sample_table3 (
  id int primary key,
  c1 int unique,
  c2 text not null,
  c3 text default 'abc',
  c4 timestamp default now()
)
alter table {old_table_name} rename to {new_table_name}
alter table {table_name} owner to {new_role}
alter table {table_name} rename column {old_column_name} to {new_column_name}
alter table {table_name} add column {DEFINE}
alter table {table_name} drop column {DEFINE}

-- 主キー
-- 制約名: {table_name}_pkey
create table {table_name} (c1 int primary key)
alter table {table_name} add primary key (c1)
alter table {table_name} add constraint {pri_keyname} primary key (c1)
alter table {table_name} drop constraint {table_name}_pkey

-- ユニーク
create table {table_name} (c1 int unique)
alter table {table_name} add unique (c1)
alter table {table_name} add constraint {table_name}_c1_key unique (c1)
alter table {table_name} drop constraint {table_name}_c1_key

-- not null
create table {table_name} (c1 int not null)
alter table {table_name} alter column c1 set not null
alter table {table_name} alter column c1 drop not null

-- foreign key
create table {table_name} (c1 int references {ref_table_name}({ref_column_name}) on delete cascade on update cascade)
create table {table_name} (c1 int foreign key (c1) references {ref_table_name}({ref_column_name}) on delete cascade on update cascade)
alter table {table_name} add constraint {table_name}_fkey foreign key (column_name) references {ref_table_name}({ref_column_name}) on delete cascade on update cascade

-- check
alter table {table_name} add constraint {table_name}_{column_name}_check check({expr})

-- parition
-- from 以上 to 未満
create table tbl (c1 serial, c2 text, c3 date) partition by range(c3);
create table tbl_y2011m10 partition of tbl for values from ('2011-10-01') to ('2019-10-01');
create table tbl_y2019m10 partition of tbl for values from ('2019-10-01') to ('2020-10-01');
create table tbl_y2020m10 partition of tbl for values from ('2020-10-01') to ('2022-10-01');
insert into tbl(c2, c3) values ('message', '2011-10-01');
insert into tbl(c2, c3) values ('message', '2019-10-01');
insert into tbl(c2, c3) values ('message', '2019-10-02');

alter table tbl attach partition {partition_name} for values {condition}
alter table tbl detach partition {partition_name}

Sequence

create sequence sample_seq start 10 increment 2;
select nextval('sample_seq');
select currval('sample_seq');
select setval('sample_seq');

View

create view sample_view(id, val) as select id, c2 from sample_table1;

Index

create index idx_name on sample_table1 [using index_type](column_name) where expr
TypeDesc
B-Tree一般的
GiST主に空間情報の検索に使用。2次元以上の空間に対する一致や包括の検索に用いる
GIN主に全文検索に用いられる転置インデックス。ある要素がどの列に有るかを検索するのに用いる
Hash値の一致検索のみをする際に用いる

Function / Procedure

create function sample_func(int) returns sample_table1 as $$ select * from sample_table1 limit $1 $$ LANGUAGE SQL;
create procedure sample_prc(int) as $$ select * from sample_table1 limit $1 $$ LANGUAGE SQL;

Aggregate (number)

NameDesc
abs(x)絶対値
div(x, y)x / y の整数商
mod(x, y)x / y の余剰
sqrt(x)x の平方根
power(x, y)x^y
ceil(x)少数切り上げ
floor(x)少数切り捨て (負の値に注意)
round(x), round(x, y)少数四捨五入. y で桁指定
trunc(x), trunc(x, y)少数切り捨て. y で桁指定
log(x)常用対数 log_10(x)
pi()円周率
random()0 <= x <1
NameDesc
|/x平方根
||/x立方根
x!階乗
!!x階乗
@絶対値

Aggregate (text)

列名 like '条件 (%: 0文字以上のワイルドカード. _: 1文字のワイルドカード)'
列名 similar to '条件 (like に加えて正規表現が使用可能)'
NameDesc
length, char_length文字列長
octed_lengthバイト数
substring(‘ABC’ from 2 for 3)切り出し. 1始まり
upper大文字
lower小文字
repeat(‘abc’, 2)繰り返し
replace(‘abc’, ‘ab’, ‘xx’)文字列置換
lpad(‘abc’, 2, ‘z’)左埋め
rpad(‘abc’, 2, ‘z’)右埋め
trim((leading|both|trailing) ‘z’ from ‘zabcz’)前後から指定文字を削除
ltrim(‘zabcz’, ‘z’)左から指定文字を削除
rtrim(‘zabcz’, ‘z’)右から指定文字を削除
NameDesc
||文字列結合
~, *, !正規表現、正規表現(大文字区別せず)、不一致

Aggregate (date)

NameDescRange
now()タイムスタンプトランザクション
localtimestampタイムスタンプトランザクション
localtime時刻トランザクション
current_timestampタイムスタンプトランザクション
current_time時刻トランザクション
current_date日付トランザクション
statement_timestampタイムスタンプステートメント
clock_timestampタイムスタンプ関数呼び出し時
age(f, t)差分-
extract(day from current_timestamp)抽出-
date_part(‘day’, current_timestamp)抽出-
date_trunc(‘day’, current_timestamp)切り捨て-
date '2019-01-01' + integer '7'
date '2019-01-01' + interval '7 hour'
to_date('2019-01-01', 'YYYY-MM-DD')
to_timestamp('2019-01-01 12:34:56', 'YYYY-MM-DD HH24:MI:SS')
to_number('123.45', '999.99')