やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

SQLite3ドットコマンド(.clone)

 DBを丸ごと別名コピーする。(元がインメモリでもファイルでも可)

成果物

.help

.clone NEWDB             Clone data into NEWDB from the existing database

.clone

in-memory→ファイル

 インメモリをファイルへ.cloneする。

sqlite3 :memory: \
"create table T(C text);" \
"insert into T values('AAA');" \
".clone clone.db"
T... done
sqlite3 clone.db \
"select sql from sqlite_master;" \
".headers on" \
"select * from T;"
CREATE TABLE T(C text)
C
AAA

ファイル→in-memory

sqlite3 :memory: \
".open clone.db" \
"select sql from sqlite_master;" \
".headers on" \
"select * from T;"
CREATE TABLE T(C text)
C
AAA

ファイル→ファイル

sqlite3 clone.db ".clone clone_0.db"
T... done

 バイナリ比較する。

cmp clone.db clone_0.db



 何も表示されなかったので差分なし。完全に同一ファイル。

空DBでやるとエラー

sqlite3 :memory: ".clone A.db"
Error: (7) out of memory on [SELECT name, sql FROM sqlite_master WHERE type='table']
Error: (7) out of memory on [SELECT name, sql FROM sqlite_master WHERE type!='table']

 ファイルは出力されるが、テーブルはない。元からないので当然。

sqlite3 A.db ".tables"



 対話モードでも同じ。

sqlite3
.clone A.db
Error: (7) out of memory on [SELECT name, sql FROM sqlite_master WHERE type='table']
Error: (7) out of memory on [SELECT name, sql FROM sqlite_master WHERE type!='table']
.tables



.backupとの違い

Cmd 用途
.clone 既存ならエラー
.backup 既存でも上書き

 .cloneは出力先ファイルが既存だとエラーになる。

sqlite3 :memory: \
"create table T(C text);" \
"insert into T values('AAA');" \
".clone clone.db"
sqlite3 :memory: \
"create table T(C text);" \
"insert into T values('AAA');" \
".clone clone.db"
File "clone.db" already exists.

 .backupは出力先ファイルが既存でも上書きする。

sqlite3 :memory: \
"create table T(C text);" \
"insert into T values('A');" \
".backup ./some.backup"
sqlite3 :memory: \
"create table T(C text);" \
"insert into T values('B');" \
".backup ./some.backup"
sqlite3 :memory: \
".restore ./some.backup" \
"select * from T;"
B

他の方法

 .cloneは単にファイルコピーするだけだというなら、シェルコマンドを使う方法もある。

cp

cp -au clone.db clone_cp.db
  • -a: 属性もできるかぎりコピー
  • -u: コピー元がコピー先より新しいか新規ファイルのときのみコピー
cmp clone.db clone_cp.db



 .cloneは更新日時などの属性まではコピーしていなかった。そこまでコピーしたいならcpシェルコマンドを使うべき。

 または-iを使う。

cp -ai clone.db clone_cp.db
cp: 'clone_cp.db' を上書きしますか?
  • -i: ファイルが既存のとき上書き確認する(y/n

 または-n

cp -an clone.db clone_cp.db
  • -n: ファイルが既存なら上書きしない

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux

前回まで