前回のポスト PostgreSQL データベースのバックアップとリストア ではデータベースに一つのテーブルしか存在していなかったので、 今回は複数(2つ)のテーブルがあった場合にどうなるか調べてみます。
例によって PostgreSQL を Docker で動かして、ディレクトリ形式でのバックアップとリストアを試します。
環境:
$ lsb_release -a|grep Description
Description: Ubuntu 24.04.1 LTS
$ docker --version
Docker version 27.2.0, build 3ab4256
$ kotlin -version
Kotlin version 2.1.0-release-394 (JRE 17.0.2+8-86)
次のように docker run して PostgreSQL をパスワードなしで起動:
$ docker run --rm -d -p 5432:5432 --name my-postgre -e POSTGRES_HOST_AUTH_METHOD=trust postgres
psql コマンドで pokemon_db を作成:
$ psql -U postgres -h localhost -c "CREATE DATABASE pokemon_db;"
そして Kotlin Script でデータを用意:
// psql.main.kts
@file:Repository("https://repo1.maven.org/maven2/")
@file:DependsOn("org.postgresql:postgresql:42.7.5")
@file:DependsOn("com.zaxxer:HikariCP:6.2.1")
import com.zaxxer.hikari.HikariDataSource
import com.zaxxer.hikari.HikariConfig
data class Db(
val driver: String,
val url: String,
val user: String,
val password: String)
val toConfig: (Db)->HikariConfig = { db->
HikariConfig().apply {
setDriverClassName( db.driver )
setJdbcUrl( db.url )
setUsername(db.user)
setPassword(db.password)
}
}
val db = Db(
"org.postgresql.Driver",
"jdbc:postgresql://localhost/pokemon_db",
"postgres",
"")
val ds = HikariDataSource(toConfig(db))
ds.connection.use { connection->
connection.createStatement().use { st->
// create tables:
val sql0 = listOf(
"DROP TABLE IF EXISTS trainers;",
"CREATE TABLE trainers(id SERIAL PRIMARY KEY, name VARCHAR(128));",
"DROP TABLE IF EXISTS pokemons;",
"CREATE TABLE pokemons(id SERIAL PRIMARY KEY, name VARCHAR(128), trainerId INTEGER);",
).joinToString("")
st.executeUpdate(sql0)
// insert trainers:
listOf(
"INSERT INTO trainers (name) VALUES('Satoshi');",
"INSERT INTO trainers (name) VALUES('Kasumi');",
).forEach { sql->
st.executeUpdate(sql)
}
// insert pokemons:
listOf(
"INSERT INTO pokemons (name, trainerId) VALUES('Pikachu', 1);",
"INSERT INTO pokemons (name, trainerId) VALUES('Squirtle', 1);",
"INSERT INTO pokemons (name, trainerId) VALUES('Psyduck', 2);",
"INSERT INTO pokemons (name, trainerId) VALUES('Golduck', 2);",
).forEach { sql->
st.executeUpdate(sql)
}
}
}
実行します。
$ kotlin psql.main.kts
意図通りデータが作成できたか確認します。
$ psql -U postgres -h localhost -d pokemon_db
pokemon_db=# SELECT * FROM trainers;
id | name
----+---------
1 | Satoshi
2 | Kasumi
(2 rows)
pokemon_db=# SELECT * FROM pokemons;
id | name | trainerid
----+----------+-----------
1 | Pikachu | 1
2 | Squirtle | 1
3 | Psyduck | 2
4 | Golduck | 2
(4 rows)
いい感じです。
トレーナに対応するポケモンが意図通りかも確認してみます。
pokemon_db=# SELECT trainers.name, pokemons.name FROM trainers, pokemons WHERE trainers.id=pokemons.trainerid;
name | name
---------+----------
Satoshi | Pikachu
Satoshi | Squirtle
Kasumi | Psyduck
Kasumi | Golduck
(4 rows)
OKです。
前回同様に pg_dump コマンドを実行:
$ pg_dump -U postgres -h localhost -Fd pokemon_db -f pokemon_db.dump
作成された pokemon_db.dump/ ディレクトリを確認:
.
└── pokemon_db.dump
├── 3367.dat.gz
├── 3369.dat.gz
└── toc.dat
テーブルごとに .dat.gz ができる感じなのでしょうか(わかりません)。
データベースをリセットするために、 一旦 docker stop して再度 docker run します。
$ docker ps
$ docker stop <CONTAINER ID>
$ docker run --rm -d -p 5432:5432 --name my-postgre -e POSTGRES_HOST_AUTH_METHOD=trust postgres
データベースを作成:
$ psql -U postgres -h localhost -c "CREATE DATABASE pokemon_db;"
リストアを実行:
$ pg_restore -U postgres -h localhost --verbose -d pokemon_db pokemon_db.dump
リストアできたか確認:
$ psql -U postgres -h localhost -d pokemon_db
psql (17.3 (Ubuntu 17.3-1.pgdg24.04+1))
Type "help" for help.
pokemon_db=# SELECT trainers.name, pokemons.name FROM trainers, pokemons WHERE trainers.id=pokemons.trainerid;
name | name
---------+----------
Satoshi | Pikachu
Satoshi | Squirtle
Kasumi | Psyduck
Kasumi | Golduck
(4 rows)
意図通りリストアできました。
以上です。