やってみる

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

SQLite3のテーブル&レコード作成を.importで行う(一時ファイル作らず)

 ファイルパスでなくshコマンドでTSVを作る。

成果物

.import

 SQLite3の内部コマンド.importは、TSVファイルからテーブルやレコードを作成するコマンドである。

sqlite3 :memory: '.help import'
.import FILE TABLE       Import data from FILE into TABLE
   Options:
     --ascii               Use \037 and \036 as column and row separators
     --csv                 Use , and \n as column and row separators
     --skip N              Skip the first N rows of input
     -v                    "Verbose" - increase auxiliary output
   Notes:
     *  If TABLE does not exist, it is created.  The first row of input
        determines the column names.
     *  If neither --csv or --ascii are used, the input mode is derived
        from the ".mode" output mode
     *  If FILE begins with "|" then it is a command that generates the
        input text.

 和訳すると以下。

.import FILE TABLE FILEからTABLEにデータをインポートします。
   オプション:
     --ascii \ 037と\ 036を列と行の区切り文字として使用します
     --csv列と行の区切り文字として、および\ nを使用します
     --skip N入力の最初のN行をスキップします
     -v "Verbose"-補助出力を増やします
   ノート:
     * TABLEが存在しない場合は作成されます。入力の最初の行
        列名を決定します。
     * --csvも--asciiも使用されていない場合、入力モードが導出されます
        「.mode」出力モードから
     * FILEが "|"で始まる場合その後、それはを生成するコマンドです
        入力テキスト。

 基本的には第一引数にファイルパスを、第二引数にテーブル名を指定する。

.import FILE TABLE

 TSVの書式。テーブルが存在しない場合、1行目を列名として解釈する。テーブルが既存の場合、1行目もデータ行とする。--skip 1とすると1行目を飛ばす。

列名A  列名B 列名C ...
A1  B1  C1
A2  B2  C2
A3  B3  C3
...

 最後の一文に注目。

  • 英文: If FILE begins with "|" then it is a command that generates the input text.
  • 和訳: FILEが"|"で始まる場合は、入力テキストを生成するコマンドです。

 なんと、ファイルパスでなくコマンド入力できるらしい。bashのプロセス置換みたいなことがしたいのだが、できるのか?

import <(paste <(echo {1..26} | tr ' ' '\n') <(echo {A..Z} | tr ' ' '\n')) Names

 というのが、今回のお題。

.import "|..." "$TABLE_NAME"

sqlite3 :memory: '.mode tabs' '.headers on' \
'.import "|echo \"Id\tName\"; echo \"1\tYamada\";" Names' \
'select * from sqlite_master' \
'select * from Names'
type name    tbl_name    rootpage    sql
table   Names   Names   2  CREATE TABLE Names(
  "Id" TEXT,
  "Name" TEXT
)
Id  Name
1  Yamada

 できた!

ブレース展開できない

sqlite3 :memory: '.mode tabs' '.headers on' \
'.import "|echo {A..Z}" Names' \
'select * from sqlite_master' \
'select * from Names'
type name    tbl_name    rootpage    sql
table   Names   Names   2  CREATE TABLE Names(
  "{A..Z}" TEXT
)

 echo {A..Z}のブレース展開がされない。なぜ?

 おそらくSQLite3が.import |で使っているシェルはshなのだろう。ブレース展開はshにはない。bashの機能。ブレース展開されないってことは、bashでなくshを使っていると思われる。

 shじゃ不便だよ!

所感

 ということで、次回はTSVをbashで作成する。そしてSQLite3にTSVをstdinで渡す。

前回まで

対象環境

$ uname -a
Linux raspberrypi 4.19.97-v7l+ #1294 SMP Thu Jan 30 13:21:14 GMT 2020 armv7l GNU/Linux