接続中のDBを一覧する。
成果物
.help
.databases List names and files of attached databases
.databases
インメモリ
sqlite3 :memory: ".databases"
main:
ファイル
sqlite3 A.db ".databases"
main: /tmp/work/A.db
attach
sqlite3 :memory: \ "attach database 'A.db' as 'A';" \ ".databases"
main: A: /tmp/work/Sqlite3.DotCommand.clone.20190819072205/A.db
DB保存パス | DB名 |
---|---|
:memory: |
main |
A.db |
A |
特殊なDB名
以下のDB名は予約されているためattach
のas
句で使えない。
DB名 | 概要 |
---|---|
main |
sqlite3 の第一引数で開いたDBの名前 |
temp |
一時テーブルや一時データオブジェクトを保持するDBの名前 |
使うとエラーが出る。
sqlite3 :memory: \ "attach database 'A.db' as 'temp';" \ ".databases"
Error: database temp is already in use
sqlite3 :memory: \ "attach database 'A.db' as 'main';" \ ".databases"
Error: database main is already in use
main
の名前を変更したい
その方法は見つけられなかった。代案としてインメモリをmain
としてattach
する方法を提案する。
期待値は以下。
保存パス | DB名 |
---|---|
A.db |
A |
B.db |
B |
テスト用DBファイル作成。
sqlite3 A.db ".exit" sqlite3 B.db ".exit"
attach
して名前を付ける。
sqlite3 :memory: \ "attach database 'A.db' as 'A';" \ "attach database 'B.db' as 'B';" \ ".databases"
main: A: /tmp/work/A.db B: /tmp/work/B.db
名前付きインメモリ
以下の2パターンのみ可能。
- 同一インメモリDBとして共有する(テーブル結合可)
- 異なるインメモリDBとしてテーブル結合できず
以下はできない。
- 異なるインメモリDBとして
attach
する
インメモリDBは通常、1プロセス内に1つだけ作成できる。また、シェルでsqlite3 :memory:
コマンドを実行する際も1プロセス内になる。よってインメモリDBを同一プロセス内に2つ以上作ることはできないため、区別する必要もない。区別のために名付ける必要もない。
ただし、Tclなどプログラムのコード内では、1つのプロセス内で複数のDBコネクションを持つことができる。このとき、インメモリDBを複数開くと、別々の無名インメモリDBとなる。これらはATTACH
不可。
もし異なるインメモリDBを作り、それらのテーブルを使いたいなら、URIパラメータfile:$db_name?mode=memory&cache=shared
を使えば可能。ただしインメモリDBは一つだけでありattach
文のようにDB名を付与することは不可。同一DB内にあるものとして操作する。
名前付きインメモリの共有
名前付きインメモリを共有するなら成功した。
named_memory_shared.tcl
package require sqlite3 proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory&cache=shared -uri true } proc create { db tbl_name } { $db eval "CREATE TABLE $tbl_name (id INT,name TEXT);" } proc insert { db tbl_name } { $db eval "INSERT INTO $tbl_name VALUES (1,'yamada');" } proc show { db tbl_name } { set result [$db eval "SELECT * FROM $tbl_name;"] foreach row $result { puts $row } } openInMem dbA1 "memdbA" create dbA1 "AAA" openInMem dbA2 "memdbA" insert dbA2 "AAA" show dbA1 "AAA" show dbA2 "AAA" openInMem dbB1 "memdbB" create dbB1 "BBB" openInMem dbB2 "memdbB" insert dbB2 "BBB" show dbB1 "BBB" show dbB2 "BBB" # no such table #dbA1 eval { select * from BBB } #dbA2 eval { select * from BBB } #dbB1 eval { select * from AAA } #dbB2 eval { select * from AAA } dbA1 close dbA2 close dbB1 close dbB2 close
実行。できた。
$ tclsh sqlite_shared_name_2.tcl 1 yamada 1 yamada 1 yamada 1 yamada
共有するため、別々DBであるかのように区別することができない。
名前付きインメモリのattach
は不可?
ファイルが作成されてしまった。
package require sqlite3 #proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory&cache=shared -uri true } proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory -uri true } openInMem Main "Main" openInMem Users "Users" openInMem Items "Items" Users eval { create table users(id integer primary key, name text, has text); } Users eval { insert into users(name,has) values('Yamada','[1,2]'); } Users eval { insert into users(name,has) values('Suzuki','[1]'); } Users eval { insert into users(name,has) values('Tanaka','[]'); } Items eval { create table items(id integer primary key, name text); } Items eval { insert into items(name) values('おにぎり'); } Items eval { insert into items(name) values('日の丸弁当'); } Items eval { insert into items(name) values('たくあん'); } set res [Users eval { select * from users; }] puts $res set res [Items eval { select * from items; }] puts $res Main eval { attach database Users as U; } Main eval { attach database Items as I; } set res [Main eval { pragma database_list; }] puts $res #Main eval { select * from U.users; } #Main eval { select * from Users.users; } #Main eval { select * from 2.users; } #Main eval { select * from users; } #Main eval { select json_each((select has from U.users where U.users.name='Yamada')); } Items close Users close Main close
1 Yamada {[1,2]} 2 Suzuki {[1]} 3 Tanaka {[]} 1 おにぎり 2 日の丸弁当 3 たくあん 0 main {} 2 U /tmp/work/Users 3 I /tmp/work/Items
attach
できているように見える。だが、コメントアウトした以下のコードを実行すると「テーブルがない」エラーになる。
#Main eval { select * from U.users; }
no such table: U.users while executing "Main eval { select * from U.users; }" (file "0.tcl" line 27)
以下も同様。
Main eval { select * from Users.users; } Main eval { select * from users; }
以下に至っては解析不能。.databases
の結果にidらしき数値が見えたので念のため試した。
Main eval { select * from 2.users; }
unrecognized token: "2.users"
しかも実行するとUsers
,Items
ファイルが作成されていた。もはやインメモリですらない。その原因はattach
。これを実行したときにファイルが作成されるようだ。
- インメモリDBを複数作ったら別々のDBになってしまう
cache=shared
すると統合される- 別名のDBとして扱うことはできない(
select DbName.TableName.ColumnName;
のようなDbName
付与不可)
- 別名のDBとして扱うことはできない(
attach
するとファイル化されてしまう
DB共有
named_memory_shared_2.tcl
package require sqlite3 proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory&cache=shared -uri true } #proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory -uri true } openInMem Main "Users" openInMem Main "Items" Main eval { create table users(id integer primary key, name text, has text); } Main eval { insert into users(name,has) values('Yamada','[1,2]'); } Main eval { insert into users(name,has) values('Suzuki','[1]'); } Main eval { insert into users(name,has) values('Tanaka','[]'); } Main eval { create table items(id integer primary key, name text); } Main eval { insert into items(name) values('おにぎり'); } Main eval { insert into items(name) values('日の丸弁当'); } Main eval { insert into items(name) values('たくあん'); } set res [Main eval { pragma database_list; }] puts $res set res [Main eval { select * from users; }] puts $res set res [Main eval { select * from items; }] puts $res set res [Main eval { select json_each.value from users u, json_each(u.has); }] puts $res set res [Main eval { select json_each.value from users u, json_each(u.has) where json_valid(u.has) and u.name='Yamada'; }] puts $res set res [Main eval { select name from items, (select json_each.value from users u, json_each(u.has) where json_valid(u.has) and u.name='Yamada') as has where has.value=items.id; }] puts $res Main close
出力結果。
0 main {} 1 Yamada {[1,2]} 2 Suzuki {[1]} 3 Tanaka {[]} 1 おにぎり 2 日の丸弁当 3 たくあん 1 2 1 1 2 おにぎり 日の丸弁当
最後の行に「おにぎり」「日の丸弁当」がある。これはYamada
がhas
していたitems
である。テーブルは共有された。
念の為、DBファイルが出力されていないことを確認。
ls -1 | grep -e 'Main' -e 'Users' -e 'Items'
同一テーブル名ならどうなる?
同一変数名
named_memory_shared_3.tcl
package require sqlite3 proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory&cache=shared -uri true } openInMem Main "Users" openInMem Main "Items" Main eval { create table users(id integer primary key, name text, has text); } Main eval { create table users(id integer primary key, name text, has text); } Main close
table users already exists while executing "Main eval { create table users(id integer primary key, name text, has text); }" (file "named_memory_shared_4.tcl" line 9)
異なる変数名
named_memory_shared_4.tcl
package require sqlite3 proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory&cache=shared -uri true } #proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory -uri true } openInMem Users "Users" openInMem Items "Items" Users eval { create table users(id integer primary key, name text, has text); } Items eval { create table users(id integer primary key, name text, has text); } Users close Items close
エラーなし。あれ?
named_memory_shared_4_1.tcl
package require sqlite3 proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory&cache=shared -uri true } #proc openInMem { db db_name } { sqlite3 $db file:$db_name?mode=memory -uri true } openInMem Users "Users" openInMem Items "Items" Users eval { create table users(id integer primary key, name text, has text); } Users eval { insert into users(name, has) values('A', '[1]'); } Items eval { create table users(id integer primary key, name text, has text); } Items eval { insert into users(name, has) values('B', '[2]'); } set res [Users eval { select * from users; }] puts $res set res [Items eval { select * from users; }] puts $res Users close Items close
tclsh named_memory_shared_4.tcl
1 A {[1]} 1 B {[2]}
それぞれ別のDBとなり共有されず。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- SQLite 3.29.0
- MeCab 0.996ユーザ辞書
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux
前回まで
- SQLite3学習をはじめよう
- SQLite3学習 SQLiteについて
- SQLite3学習 SQLiteの適切な用途
- SQLite3学習 SQLiteの特徴
- SQLite3学習 SQLiteのクセ
- SQLite3学習 データ型とアフィニティ
- SQLite3学習 演算子の一覧
- SQLite3学習 よくある質問
- SQLite3学習 SQLiteダウンロード&コンパイル
- SQLite3学習 Tclで操作する
- SQLite3学習 ビルドオプション動作確認(SQLITE_ALLOW_URI_AUTHORITY)
- SQLite3学習 面白そうなコンパイルオプション
- SQLite3学習 SQLiteの拡張について
- SQLite3学習 JSON拡張
- SQLite3学習 JSON拡張(json_extract)
- SQLite3学習 JSON拡張(json_each)
- SQLite3学習 JSON拡張(json_tree オブジェクト→行)
- SQLite3学習 JSON拡張(json_tree オブジェクトツリー→行)
- SQLite3学習 JSON拡張(json_tree オブジェクト配列→行)
- SQLite3学習 JSON拡張(json_group_array 行→配列)
- SQLite3学習 JSON拡張(json_group_object 行→オブジェクト)
- SQLite3学習 JSON拡張(json_array_length)
- SQLite3学習 JSON拡張(json_type)
- SQLite3学習 JSON拡張(json_valid)
- SQLite3学習 JSON拡張(json_quote)
- SQLite3学習 JSON拡張(json_array)
- SQLite3学習 JSON拡張(json_object)
- SQLite3学習 JSON拡張(json_patch)
- SQLite3学習 JSON拡張(json_insert)
- SQLite3学習 JSON拡張(json_replace)
- SQLite3学習 JSON拡張(json_set)
- SQLite3学習 JSON拡張(json_remove)
- SQLite3学習 全文検索(FTS5)
- SQLite3学習 全文検索FTSを日本語で使う方法を調べてみた
- 形態素解析MeCabをインストールする
- SQLite3学習 全文検索FTS5のMeCab用トークナイザを実装する
- SQLite3学習 FTS5+MeCabでクエリ構文
- SQLite3学習 FTS5のテーブル作成と初期化
- SQLite3学習 FTS5の補助関数
- SQLite3学習 FTS5のfts5vocab仮想テーブル
- SQLite3学習 再帰クエリ(WITH RECURSIVE)
- SQLite3学習 R-Treeモジュール
- SQLite3学習 ファイル入出力(SQL集計)
- SQLite3学習 拡張関数(generate_series)
- SQLite3謎 主キーの型をintにするとinsertで値を省略したらNULLになってしまう
- SQLite3学習 入出力関数(fsdir, readfile, writefile, edit)
- SQLite3ビルド コンパイルオプションを付与する方法(CFLAGS等))
- SQLite3 コンパイルオプション確認方法(pragma compile_options)
- SQLite3ビルド ICUを有効にする(SQLITE_ENABLE_ICU)
- SQLite3拡張 ICUを動的ロードする
- SQLite3拡張 ICUでcollateする
- SQLite3拡張 ICUで全文検索する(FTS4)
- SQLite3拡張 SQL関数一覧(pragma function_list)
- SQLite3拡張 仮想テーブルモジュール一覧(pragma module_list)
- SQLite3拡張 プラグマ一覧(pragma pragma_list)
- SQLite3謎 values()構文
- SQLite3学習 インタフェース概要
- SQLite3学習 CLI起動引数(-A)Archive
- SQLite3ビルド SQLITE_HAVE_ZLIBコンパイルオプション付与するも確認できず
- SQLite3学習 CLI(-readonly)
- MeCabユーザ辞書の作り方(Wikipediaの題名を名詞とした)
- SQLite3学習 CLI(-zip)
- SQLite3ドットコマンド(.archive)
- SQLite3ドットコマンド(.auth)断念
- SQLite3ドットコマンド(.backup .restore)
- SQLite3ドットコマンド(.read)
- SQLite3ドットコマンド(.dump)
- SQLite3ドットコマンド(.bail)謎
- SQLite3ドットコマンド(.binary)
- SQLite3ドットコマンド(.cd)
- SQLite3ドットコマンド(.changes)
- SQLite3ドットコマンド(.testcase .check)
- SQLite3ドットコマンド(.clone)