プログラミング · PostgreSQL · SQL
PostgreSQL構文のタイピング練習
PostgreSQL の SQL 構文を、初級から上級までの4つのリスト(152個)で打って覚えます。AS・IN・AND/OR などの条件から、CREATE TABLE と制約まで、SQL を書く形のまま練習できます。
4リスト・152語
無料・ログインなしで練習できます。押すとこのパックをフォローし、すぐに練習が始まります。
収録している言葉
PostgreSQL構文(初級)
| 打つ言葉 | 意味・補足 |
|---|---|
| SHOW server_version; | 対象バージョン:例の利用条件(PostgreSQL 15以降を想定した主要構文。各例は独立した断片で、表・列・権限等の準備が必要) |
| SELECT 1; SELECT 2; | ;:文を区切る |
| SELECT 'Pomo'; | '文字列':文字列リテラル(文字列中の単一引用符は''で表す) |
| SELECT name AS "表示名" FROM users; | "識別子":識別子の引用(引用しない識別子は小文字として扱う。文字列の引用とは異なる) |
| SELECT * FROM public.users; | スキーマ.表:スキーマ修飾(同名オブジェクトの曖昧さを避ける) |
| SELECT id, name FROM users; | SELECT / FROM:列を取得 |
| SELECT * FROM users; | SELECT *:全列を取得(列追加の影響を受けやすい) |
| SELECT * FROM users WHERE age >= 20; | WHERE:条件で絞る |
| SELECT * FROM users WHERE age <> 20; | 比較演算子:比較(NULLとの通常比較は真偽がunknownになる) |
| SELECT * FROM users WHERE email IS NULL; | IS NULL / IS NOT NULL:NULLの判定 |
| SELECT DISTINCT department_id FROM users; | DISTINCT:重複行を除く(選択した列全体で重複判定) |
| SELECT COUNT(*) FROM users; | COUNT(*):行数 |
| SELECT COUNT(email) FROM users; | COUNT(列):非NULLの件数(NULLを数えない) |
| SELECT MIN(age), MAX(age) FROM users; | MIN / MAX:最小・最大 |
| TRUNCATE TABLE orders; | TRUNCATE:表をまとめて空にする(強いロックを取る。DELETEトリガーは発火しない) |
| TRUNCATE TABLE orders RESTART IDENTITY; | TRUNCATE ... RESTART IDENTITY:表を空にし採番も戻す(全データ削除。表に所有されるシーケンスが対象) |
| ALTER TABLE users ADD COLUMN nickname text; | ALTER TABLE ADD COLUMN:列を追加 |
| ALTER TABLE users DROP COLUMN nickname; | ALTER TABLE DROP COLUMN:列を削除(列データを失う) |
| DROP TABLE notes; | DROP TABLE:表を削除(表とデータを失う。CASCADEは依存オブジェクトにも影響) |
| CREATE SCHEMA app; | CREATE SCHEMA:スキーマを作る |
| SELECT 123.45::numeric(12, 2); | numeric(p,s):正確な小数(金額等。精度・スケールに制約) |
| SELECT 0.1::double precision; | double precision:近似の浮動小数点(正確な10進小数ではない) |
| SELECT true, false, NULL::boolean; | boolean:真偽値 |
| SELECT INTERVAL '7 days'; | interval:期間 |
| SELECT gen_random_uuid(); | uuid:UUID(例の関数はPostgreSQL 15以降で組込み) |
| SELECT decode('4869', 'hex'); | bytea:バイナリ |
| SELECT ROUND(123.456::numeric, 2); | ROUND:小数を丸める(小数桁指定の例はnumeric) |
| SELECT CURRENT_DATE, NOW(); | CURRENT_DATE / NOW:現在の日付・日時(NOWはトランザクション開始時点) |
| SELECT clock_timestamp(); | clock_timestamp:実際の現在時刻(同一文の実行中にも変化し得る) |
| SELECT NOW() - INTERVAL '7 days'; | 日時 + INTERVAL:日時の加減算 |
| SELECT * FROM generate_series(1, 5); | generate_series:連番等を生成 |
| DROP INDEX users_age_idx; | DROP INDEX:インデックス削除(その索引が存在する場合) |
| REFRESH MATERIALIZED VIEW user_totals; | REFRESH MATERIALIZED VIEW:保存結果を更新(通常は参照をブロック。CONCURRENTLYには適切な一意索引等が必要) |
| ANALYZE users; | ANALYZE:統計情報を更新(対象に適切な権限が必要) |
| VACUUM (ANALYZE) users; | VACUUM:不要領域の再利用等(トランザクションブロック内不可。通常OSへ容量を返す処理ではない) |
| CREATE ROLE app_reader; | CREATE ROLE:ロール作成(適切な管理権限が必要) |
| REVOKE SELECT ON users FROM app_reader; | REVOKE:権限を取り消す(他ロール経由等の権限は残る場合がある) |
| SHOW TimeZone; | SHOW:設定を確認 |
PostgreSQL構文(中級1)
| 打つ言葉 | 意味・補足 |
|---|---|
| SELECT name AS display_name FROM users AS u; | AS:別名を付ける |
| SELECT * FROM users WHERE id IN (1, 2, 3); | IN:候補に含まれるか |
| SELECT * FROM users WHERE id NOT IN (1, 2); | NOT IN:候補に含まれないか(候補にNULLを含むと意図しない結果になり得る。NOT EXISTSも検討) |
| SELECT * FROM users WHERE age BETWEEN 20 AND 29; | BETWEEN:両端を含む範囲(日時では>=と<の半開区間が便利) |
| SELECT * FROM users WHERE age IS DISTINCT FROM 20; | IS DISTINCT FROM:NULLを含めた不等比較(NULLも比較可能な値として扱う) |
| SELECT * FROM users WHERE name LIKE 'Po%'; | LIKE:パターン一致(%は任意長、_は任意1文字) |
| SELECT * FROM users WHERE name ILIKE 'po%'; | ILIKE:大文字小文字を区別しない一致(大文字小文字の扱いはロケール等に依存) |
| SELECT * FROM users WHERE name ~* '^po'; | ~ / ~*:正規表現一致(~*は大文字小文字を区別しない) |
| SELECT * FROM users ORDER BY age ASC NULLS LAST; | NULLS FIRST / LAST:NULLの並び位置 |
| SELECT * FROM users ORDER BY id LIMIT 20 OFFSET 40; | LIMIT / OFFSET:取得件数・開始位置(一意に並ぶORDER BYを指定。大きなOFFSETは負荷になり得る) |
| SELECT COUNT(DISTINCT department_id) FROM users; | COUNT(DISTINCT 列):非NULLの異なる値の数 |
| SELECT SUM(amount), AVG(amount) FROM orders; | SUM / AVG:合計・平均(対象なしの場合は通常NULL) |
| SELECT ARRAY_AGG(id ORDER BY id) FROM users; | ARRAY_AGG:配列へ集約 |
| SELECT JSONB_AGG(name ORDER BY id) FROM users; | JSONB_AGG:JSON配列へ集約 |
| SELECT id FROM users EXCEPT SELECT user_id FROM orders; | INTERSECT / EXCEPT:共通部分・差集合(列数と型に互換性が必要) |
| INSERT INTO users (name) VALUES ('A'), ('B'); | 複数行INSERT:複数行を追加 |
| INSERT INTO counters DEFAULT VALUES RETURNING id; | DEFAULT VALUES:既定値で追加(IDENTITYの例で作成するcounters表向け。全必須列に既定値がある表で使用) |
| DELETE FROM users WHERE id = 1 RETURNING id; | DELETE / WHERE:行を削除(WHEREなしは全行削除。外部キー制約で拒否される場合がある) |
| CREATE TABLE items ( id bigint PRIMARY KEY ); | PRIMARY KEY:主キー(一意かつNOT NULL) |
| ALTER TABLE users ALTER COLUMN email SET NOT NULL; | NOT NULL:NULL禁止(既存NULLがあると失敗) |
| ALTER TABLE users ALTER COLUMN active SET DEFAULT true; | DEFAULT:既定値(既存行の値は変更しない) |
| ALTER TABLE users DROP CONSTRAINT users_name_unique; | DROP CONSTRAINT:制約を削除(制約が存在する場合) |
| SELECT 42::integer, 10000000000::bigint; | integer / bigint:整数 |
| SELECT 'hello'::text, 'abc'::varchar(10); | text / varchar(n):文字列(varchar(n)は長さ制限) |
| SELECT TIMESTAMPTZ '2026-01-01 12:00:00+09'; | timestamptz:時点を扱う日時(表示はセッションTimeZoneに依存。元の地域名は保持しない) |
| SELECT '{"name":"Pomo"}'::jsonb; | json / jsonb:JSON(jsonbはインデックス対応。キー順・重複キーの保持等がjsonと異なる) |
| SELECT ARRAY['go', 'sql']::text[]; | 型[] / ARRAY:配列(PostgreSQLの配列添字は通常1から) |
| SELECT COALESCE(email, '未登録') FROM users; | COALESCE:最初の非NULL値 |
| SELECT amount / NULLIF(0, 0) FROM orders; | NULLIF:等しいならNULL(ゼロ除算回避等) |
| SELECT CAST('123' AS integer), '123'::integer; | CAST / :::型変換(変換不可はエラー) |
| SELECT EXTRACT(YEAR FROM created_at) FROM users; | EXTRACT:日時の要素を取得 |
| SELECT NOW() AT TIME ZONE 'Asia/Tokyo'; | AT TIME ZONE:タイムゾーンの解釈・変換(入力型により戻り値型・意味が異なる) |
| SELECT profile #>> '{address,city}' FROM users; | #> / #>>:JSONの深いパス |
| SELECT * FROM users WHERE profile ? 'name'; | ?:JSONBのキー等の存在(ドライバーによってプレースホルダー記号との扱いに注意) |
| SELECT * FROM users WHERE 'sql' = ANY(tags); | ANY:配列要素との比較 |
| SELECT id, unnest(tags) AS tag FROM users; | unnest:配列を行へ展開 |
| BEGIN READ ONLY; SELECT * FROM users; COMMIT; | READ ONLY:読み取り専用トランザクション |
| EXPLAIN SELECT * FROM users WHERE id = 1; | EXPLAIN:実行計画を表示(通常は対象SQLを実行しない) |
PostgreSQL構文(中級2)
| 打つ言葉 | 意味・補足 |
|---|---|
| /* 1行コメント */ SELECT /* ブロックコメント */ 1; | -- / /* ... */:コメント |
| SELECT * FROM users WHERE active AND (age >= 20 OR age IS NULL); | AND / OR / NOT:条件を組み合わせる(混在時は括弧で意図を明示) |
| SELECT * FROM users ORDER BY created_at DESC, id DESC; | ORDER BY:並べ替え(指定しない取得順は保証されない) |
| SELECT * FROM users WHERE id > 100 ORDER BY id LIMIT 20; | キ―セットページング:前回の続きから取得(前回の最終id等を使用) |
| SELECT department_id, COUNT(*) FROM users GROUP BY department_id; | GROUP BY:グループ単位に集計 |
| SELECT STRING_AGG(name, ', ' ORDER BY id) FROM users; | STRING_AGG:文字列を連結(順番が必要なら集計内でORDER BY) |
| SELECT * FROM orders WHERE amount > ( SELECT AVG(amount) FROM orders ); | スカラーサブクエリ:単一値を式に使う(複数行を返すとエラー) |
| SELECT id FROM users WHERE active UNION ALL SELECT id FROM users WHERE NOT active; | UNION / UNION ALL:結果を連結(UNIONは重複排除、UNION ALLは保持) |
| INSERT INTO users (name) VALUES ('Pomo') RETURNING id, name; | RETURNING:変更した行を返す(UPDATE・DELETEでも使用可能) |
| UPDATE users SET age = age + 1 WHERE id = 1 RETURNING id, age; | UPDATE / SET / WHERE:行を更新(WHEREなしは全行更新) |
| DELETE FROM orders o USING users u WHERE o.user_id = u.id AND NOT u.active; | DELETE ... USING:結合条件で削除 |
| CREATE TABLE counters ( id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY ); | IDENTITY:自動採番列(値の連続性・欠番なしを保証しない) |
| ALTER TABLE users ADD CONSTRAINT users_name_unique UNIQUE (name); | UNIQUE:一意制約(既存の重複があると失敗。通常NULL同士は同値としない) |
| ALTER TABLE orders ADD CONSTRAINT orders_amount_positive CHECK (amount >= 0); | CHECK:行の条件制約(条件がNULLの場合も通る。必要ならNOT NULLも併用) |
| ALTER TABLE users ALTER COLUMN age TYPE bigint USING age::bigint; | ALTER COLUMN TYPE:列型を変更(ロック・書き換えの負荷が発生する場合がある) |
| ALTER TABLE users RENAME COLUMN nickname TO display_name; | RENAME COLUMN / TO:列名・表名を変更(この例はnickname列がある場合) |
| CREATE TABLE user_snapshot AS SELECT id, name FROM users; | CREATE TABLE AS:検索結果で表を作る(元表の制約・インデックス等は通常引き継がない) |
| SELECT DATE '2026-01-01', TIMESTAMP '2026-01-01 12:00:00'; | date / timestamp:日付・タイムゾーンなし日時(timestamp単独はwithout time zone) |
| SELECT name, CASE WHEN age >= 20 THEN '成人' ELSE 'その他' END FROM users; | CASE WHEN:条件に応じた値 |
| SELECT name || 'さん', CONCAT(name, 'さん') FROM users; | || / CONCAT:文字列連結(||はNULLがあると通常NULL。CONCATはNULL引数を無視) |
| SELECT LOWER(name), UPPER(name), TRIM(name) FROM users; | LOWER / UPPER / TRIM:文字列加工 |
| SELECT LENGTH(name), SUBSTRING(name FROM 1 FOR 2) FROM users; | LENGTH / SUBSTRING:長さ・部分文字列(LENGTH(text)は文字数) |
| SELECT profile->'address', profile->>'name' FROM users; | -> / ->>:JSON要素の取得(->はJSON、->>はtext) |
| SELECT * FROM users WHERE profile @ > '{"premium":true}'::jsonb; | @>:JSONB包含 |
| SELECT jsonb_build_object('id', id, 'name', name) FROM users; | jsonb_build_object:JSONBオブジェクトを構築 |
| SELECT * FROM users WHERE tags && ARRAY['go', 'sql']; | &&:配列の重なり |
| CREATE INDEX users_created_at_idx ON users(created_at); | CREATE INDEX:検索用インデックス(読み取りが速くなる場合があるが更新・容量コストが増える) |
| CREATE INDEX orders_user_created_idx ON orders(user_id, created_at DESC); | 複合インデックス:複数列のインデックス(列順・条件・並べ替えに合わせて設計) |
| CREATE INDEX users_active_idx ON users(id) WHERE active; | 部分インデックス:条件に合う行だけを索引化(クエリ条件と述語の関係が重要) |
| CREATE INDEX users_lower_email_idx ON users(LOWER(email)); | 式インデックス:式の結果を索引化 |
| CREATE INDEX users_profile_gin_idx ON users USING GIN(profile); | USING GIN:JSONB等向けGIN索引(演算子・演算子クラスにより対応が異なる) |
| CREATE INDEX CONCURRENTLY users_age_idx ON users(age); | CREATE INDEX CONCURRENTLY:書き込みを止めにくい索引作成(トランザクションブロック内不可。失敗時に無効索引が残り得る) |
| CREATE VIEW active_users AS SELECT id, name FROM users WHERE active; | CREATE VIEW:クエリをビューとして保存(通常は結果を保存しない) |
| BEGIN; UPDATE users SET active = false WHERE id = 1; COMMIT; | BEGIN / COMMIT:処理をまとめて確定(実行すると変更が確定) |
| BEGIN; UPDATE users SET active = false WHERE id = 1; ROLLBACK; | ROLLBACK:変更を取り消す(シーケンスの採番等は巻き戻らない) |
| BEGIN ISOLATION LEVEL SERIALIZABLE; SELECT * FROM users WHERE id = 1; COMMIT; | ISOLATION LEVEL:分離レベルを指定(直列化失敗時はトランザクション全体の再試行が必要) |
| BEGIN; SELECT * FROM users WHERE id = 1 FOR UPDATE; COMMIT; | FOR UPDATE:取得行を更新用にロック(ロックは通常トランザクション終了まで) |
| EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM users WHERE id = 1; | EXPLAIN ANALYZE:実行して実測計画を表示(対象SQLを実際に実行。UPDATE・DELETE等にも副作用がある) |
PostgreSQL構文(上級)
| 打つ言葉 | 意味・補足 |
|---|---|
| CREATE TABLE users ( id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name text NOT NULL, email text UNIQUE, age integer CHECK (age >= 0), active boolean NOT NULL DEFAULT true, department_id bigint, created_at timestamptz NOT NULL DEFAULT now(), profile jsonb NOT NULL DEFAULT '{}'::jsonb, tags text[] NOT NULL DEFAULT '{}' ); CREATE TABLE orders ( id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, user_id bigint REFERENCES users(id), amount numeric(12, 2) NOT NULL, status text NOT NULL DEFAULT 'pending', created_at timestamptz NOT NULL DEFAULT now() ); | サンプルテーブル:例に使う表を作成(空の検証用スキーマ向け。同名表があると失敗。以下の例を全部順番に実行する用途ではない) |
| PREPARE find_user(bigint) AS SELECT * FROM users WHERE id = $1; EXECUTE find_user(1); DEALLOCATE find_user; | $1等のパラメーター:値をパラメーター化(アプリではドライバーのパラメーターAPIを使用。識別子は値パラメーターでは置き換えられない) |
| SELECT DISTINCT ON (department_id) department_id, id, created_at FROM users ORDER BY department_id, created_at DESC, id DESC; | DISTINCT ON:グループごとに先頭行(PostgreSQL固有。DISTINCT ON式をORDER BYの左端に合わせる) |
| SELECT department_id, COUNT(*) FROM users GROUP BY department_id HAVING COUNT(*) >= 5; | HAVING:集計後に絞る(WHEREは集計前の行に作用) |
| SELECT COUNT(*) AS total, COUNT(*) FILTER (WHERE active) AS active_count FROM users; | FILTER:集計の対象を条件指定 |
| SELECT u.name, o.amount FROM users u INNER JOIN orders o ON o.user_id = u.id; | INNER JOIN:一致する行を結合 |
| SELECT u.id, o.id AS order_id FROM users u LEFT JOIN orders o ON o.user_id = u.id; | LEFT JOIN:左側を残して結合(右側へのWHERE条件で実質INNER JOINになる場合がある) |
| SELECT u.id, o.id AS order_id FROM users u FULL OUTER JOIN orders o ON o.user_id = u.id; | FULL OUTER JOIN:両側の未一致行も残す |
| SELECT u.id, s.status FROM users u CROSS JOIN ( VALUES ('pending'), ('paid') ) AS s(status); | CROSS JOIN:直積(行数が掛け算で増える) |
| SELECT u.id, x.total FROM users u JOIN ( SELECT user_id AS id, SUM(amount) AS total FROM orders GROUP BY user_id ) x USING (id); | USING:同名の結合列を指定 |
| SELECT * FROM users u WHERE EXISTS ( SELECT 1 FROM orders o WHERE o.user_id = u.id ); | EXISTS:対応する行があるか |
| SELECT * FROM users u WHERE NOT EXISTS ( SELECT 1 FROM orders o WHERE o.user_id = u.id ); | NOT EXISTS:対応する行がないか |
| WITH totals AS ( SELECT user_id, SUM(amount) AS total FROM orders GROUP BY user_id ) SELECT * FROM totals WHERE total >= 1000; | WITH / CTE:クエリに名前を付ける(必ず実体化されるわけではない) |
| WITH RECURSIVE nums(n) AS ( VALUES (1) UNION ALL SELECT n + 1 FROM nums WHERE n < 5 ) SELECT n FROM nums; | WITH RECURSIVE:再帰クエリ(終了条件が必要) |
| SELECT u.id, recent.id AS order_id FROM users u LEFT JOIN LATERAL ( SELECT id FROM orders o WHERE o.user_id = u.id ORDER BY created_at DESC, id DESC LIMIT 1 ) recent ON true; | LATERAL:左側の行を参照する副問い合わせ(ユーザーごとの最新注文など) |
| SELECT id, user_id, amount, SUM(amount) OVER ( PARTITION BY user_id ) AS user_total FROM orders; | OVER / PARTITION BY:行を残したまま集計(GROUP BYと異なり各行を残す) |
| SELECT id, ROW_NUMBER() OVER ( PARTITION BY user_id ORDER BY created_at, id ) AS n FROM orders; | ROW_NUMBER:グループ内の連番(同順位の順番も決めるなら一意な並べ替え) |
| SELECT id, RANK() OVER ( ORDER BY amount DESC ), DENSE_RANK() OVER ( ORDER BY amount DESC ) FROM orders; | RANK / DENSE_RANK:順位(RANKは同順位後に欠番、DENSE_RANKは欠番なし) |
| SELECT id, LAG(amount) OVER ( PARTITION BY user_id ORDER BY created_at, id ) FROM orders; | LAG / LEAD:前後の行の値 |
| SELECT id, SUM(amount) OVER ( ORDER BY created_at, id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS running_total FROM orders; | ROWS BETWEEN:累積の窓枠(既定の窓枠との差に注意) |
| INSERT INTO users (name, email, age) VALUES ('Pomo', 'pomo@example.com', 20); | INSERT INTO / VALUES:行を追加 |
| INSERT INTO users (name) SELECT 'User ' || n FROM generate_series(1, 3) AS g(n); | INSERT ... SELECT:検索結果を挿入 |
| INSERT INTO users (name, email) VALUES ('Pomo', 'pomo@example.com') ON CONFLICT (email) DO NOTHING; | ON CONFLICT DO NOTHING:一意競合時に追加しない(対象に適切な一意制約・インデックスが必要) |
| INSERT INTO users (name, email) VALUES ('New', 'pomo@example.com') ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name RETURNING id, name; | ON CONFLICT DO UPDATE:一意競合時に更新(EXCLUDEDは挿入予定の行) |
| UPDATE users u SET active = true FROM ( SELECT DISTINCT user_id FROM orders WHERE status = 'paid' ) o WHERE u.id = o.user_id; | UPDATE ... FROM:別の表や結果を使って更新(対象行が複数の結合行に一致しないようにする) |
| MERGE INTO users u USING ( VALUES ('pomo@example.com', 'Pomo') ) AS s(email, name) ON u.email = s.email WHEN MATCHED THEN UPDATE SET name = s.name WHEN NOT MATCHED THEN INSERT (email, name) VALUES (s.email, s.name); | MERGE:一致条件に応じて更新・追加(PostgreSQL 15以降。ON CONFLICTと同じ競合処理保証ではない) |
| CREATE TABLE notes ( id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, body text NOT NULL ); | CREATE TABLE:表を作る |
| CREATE TABLE reviews ( id bigint PRIMARY KEY, user_id bigint REFERENCES users(id) ); | FOREIGN KEY:外部キー(参照側インデックスは自動作成されない) |
| CREATE TABLE sessions ( id bigint PRIMARY KEY, user_id bigint REFERENCES users(id) ON DELETE CASCADE ); | ON DELETE CASCADE:親削除時に子も削除(意図せぬ連鎖削除に注意) |
| SELECT DATE_TRUNC('month', created_at), COUNT(*) FROM users GROUP BY DATE_TRUNC('month', created_at); | DATE_TRUNC:日時を指定単位へ切り捨て(timestamptzではTimeZoneに注意) |
| UPDATE users SET profile = jsonb_set(profile, '{premium}', 'true'::jsonb) WHERE id = 1; | jsonb_set:JSONBの一部を変更(深いパスの途中のキーがない場合等に注意) |
| CREATE MATERIALIZED VIEW user_totals AS SELECT user_id, SUM(amount) AS total FROM orders GROUP BY user_id; | CREATE MATERIALIZED VIEW:結果を保存するビュー(元表変更だけでは内容が自動更新されない) |
| BEGIN; SAVEPOINT before_change; UPDATE users SET active = false WHERE id = 1; ROLLBACK TO SAVEPOINT before_change; COMMIT; | SAVEPOINT:途中の復帰地点 |
| BEGIN; SELECT * FROM orders WHERE status = 'pending' ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1; COMMIT; | SKIP LOCKED:ロック済み行を飛ばす(ジョブキュー等向け。一般的な整合した一覧取得には不向き) |
| BEGIN; SET LOCAL lock_timeout = '3s'; SELECT * FROM users WHERE id = 1 FOR UPDATE; COMMIT; | SET LOCAL lock_timeout:ロック待機を制限(SET LOCALは現在トランザクション内だけ) |
| GRANT USAGE ON SCHEMA public TO app_reader; GRANT SELECT ON users TO app_reader; | GRANT:権限付与(既存のusers表が対象。将来の表には別設定が必要) |
| COPY ( SELECT id, name FROM users ) TO '/tmp/users.csv' WITH (FORMAT csv, HEADER true); | COPY:サーバー側CSV出力(サーバー上のパス。特別なファイル権限等が必要。クライアントのパスではない) |
| SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'users' ORDER BY ordinal_position; | information_schema:表の構造等を参照(権限で見える範囲が変わる) |