SQLite と DB Browser for SQLite で SQL入門してみる

普段データ移行はCSV読み込みなどですませてますが、今回、MS-ACCESSのシステムをデータ移行する際にExcelマスターが必要なぐらいに感じたので:innocent:、素直にSQLでやることにしました。
SQLは全く分からないので調べながら入門編:hatching_chick:としてまとめてみます。

# 対象

* SQL全く分からない方
* SQL簡単に試したい方

# SQLite

「[SQLite](https://www.sqlite.org/index.html)とは何か？」とかは色々ググってもらうとして、Railsとか昔（今も？）標準で入ってたような…とにかく軽量でファイルベース？のようなデータベースです。
データベースがファイル１つに入っているのが個人的に気に入ってます。[サーバーレス](https://www.sqlite.org/quirks.html)というのも良いですね:wink:

# SQLiteのコマンドリファレンス

SQLiteで使えるコマンドなどのリファレンスです。
https://www.sqlite.org/keyword_index.html

# SQLiteの準備

私はMacなので [Homebrew](https://brew.sh/index_ja) でインストールしましたけど、お好きにインストールしてもらえばOK。

# シェルから使ってみる

適当なフォルダとか作ってそこで実行してみます。

## 実行
sqlite3でEnterするとSQLiteの[シェルプログラム](https://www.sqlite.org/cli.html)が実行されます。

```
$ sqlite3
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
```

## ヘルプ表示
.help でヘルプが表示されます。

```
sqlite> .help
.auth ON|OFF           Show authorizer callbacks
.backup ?DB? FILE      Backup DB (default "main") to FILE
                         Add "--append" to open using appendvfs.
.bail on|off           Stop after hitting an error.  Default OFF
.binary on|off         Turn binary output on or off.  Default OFF
.cd DIRECTORY          Change the working directory to DIRECTORY
.changes on|off        Show number of rows changed by SQL
.check GLOB            Fail if output since .testcase does not match
.clone NEWDB           Clone data into NEWDB from the existing database
.databases             List names and files of attached databases
.dbconfig ?op? ?val?   List or change sqlite3_db_config() options
.dbinfo ?DB?           Show status information about the database
.dump ?TABLE? ...      Dump the database in an SQL text format
                         If TABLE specified, only dump tables matching
                         LIKE pattern TABLE.
.echo on|off           Turn command echo on or off
.eqp on|off|full       Enable or disable automatic EXPLAIN QUERY PLAN
.excel                 Display the output of next command in a spreadsheet
.exit                  Exit this program
.expert                EXPERIMENTAL. Suggest indexes for specified queries
.fullschema ?--indent? Show schema and the content of sqlite_stat tables
.headers on|off        Turn display of headers on or off
.help                  Show this message
.import FILE TABLE     Import data from FILE into TABLE
.imposter INDEX TABLE  Create imposter table TABLE on index INDEX
.indexes ?TABLE?       Show names of all indexes
                         If TABLE specified, only show indexes for tables
                         matching LIKE pattern TABLE.
.limit ?LIMIT? ?VAL?   Display or change the value of an SQLITE_LIMIT
.lint OPTIONS          Report potential schema issues. Options:
                         fkey-indexes     Find missing foreign key indexes
.log FILE|off          Turn logging on or off.  FILE can be stderr/stdout
.mode MODE ?TABLE?     Set output mode where MODE is one of:
                         ascii    Columns/rows delimited by 0x1F and 0x1E
                         csv      Comma-separated values
                         column   Left-aligned columns.  (See .width)
                         html     HTML <table> code
                         insert   SQL insert statements for TABLE
                         line     One value per line
                         list     Values delimited by "|"
                         quote    Escape answers as for SQL
                         tabs     Tab-separated values
                         tcl      TCL list elements
.nullvalue STRING      Use STRING in place of NULL values
.once (-e|-x|FILE)     Output for the next SQL command only to FILE
                         or invoke system text editor (-e) or spreadsheet (-x)
                         on the output.
.open ?OPTIONS? ?FILE? Close existing database and reopen FILE
                         The --new option starts with an empty file
                         Other options: --readonly --append --zip
.output ?FILE?         Send output to FILE or stdout
.print STRING...       Print literal STRING
.prompt MAIN CONTINUE  Replace the standard prompts
.quit                  Exit this program
.read FILENAME         Execute SQL in FILENAME
.restore ?DB? FILE     Restore content of DB (default "main") from FILE
.save FILE             Write in-memory database into FILE
.scanstats on|off      Turn sqlite3_stmt_scanstatus() metrics on or off
.schema ?PATTERN?      Show the CREATE statements matching PATTERN
                          Add --indent for pretty-printing
.selftest ?--init?     Run tests defined in the SELFTEST table
.separator COL ?ROW?   Change the column separator and optionally the row
                         separator for both the output mode and .import
.session CMD ...       Create or control sessions
.sha3sum ?OPTIONS...?  Compute a SHA3 hash of database content
.shell CMD ARGS...     Run CMD ARGS... in a system shell
.show                  Show the current values for various settings
.stats ?on|off?        Show stats or turn stats on or off
.system CMD ARGS...    Run CMD ARGS... in a system shell
.tables ?TABLE?        List names of tables
                         If TABLE specified, only list tables matching
                         LIKE pattern TABLE.
.testcase NAME         Begin redirecting output to 'testcase-out.txt'
.timeout MS            Try opening locked tables for MS milliseconds
.timer on|off          Turn SQL timer on or off
.trace FILE|off        Output each SQL statement as it is run
.vfsinfo ?AUX?         Information about the top-level VFS
.vfslist               List all available VFSes
.vfsname ?AUX?         Print the name of the VFS stack
.width NUM1 NUM2 ...   Set column widths for "column" mode
                         Negative values right-justify
```

## データベースの表示
.databases でデータベースファイルを表示します。

```
sqlite> .databases
main:
```

## テーブルの表示
.tables でテーブルが表示されます。

```
sqlite> .tables
```

## SQLiteシェルの終了
.quit でシェルを終了できます。

```
sqlite> .quit
```

## システムコマンドの実行

.systemコマンドに続けて、OS固有のコマンドを実行できます。


```
sqlite> .system ls
```

---
# データベースの作成
sqlite3に続けてデータベースファイル名を入力します。
何も無ければ新規に作成されますし、あれば指定したデータベースがオープンされます。

```
$ sqlite3 sample1.db
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
sqlite> .databases
main: /Users/yoshida/sample-sqlite/sample1.db
sqlite>
```

# テーブルの作成
色々やり方がありますが、素直にシェルで `create table` してみます。
列名の型に `INTEGER PRIMARY KEY` を指定するとシステムで保持するテーブルの行idのエイリアスになります。 

```
sqlite> CREATE TABLE sampletb1 (
   ...>     uid INTEGER PRIMARY KEY,
   ...>     name TEXT
   ...> );
sqlite> .tables
sampletb1
sqlite> .schema sampletb1
CREATE TABLE sampletb1 (
    uid INTEGER PRIMARY KEY,
    name TEXT
);
```

# レコードの追加
レコードを追加してみます。
先頭に設定した列は、上記でシステムの行idとなっているので、レコード追加するときには列名を指定して `(name)` 追加します。

```
sqlite> INSERT INTO sampletb1
   ...>     VALUES( 'Suzuki');
Error: table sampletb1 has 2 columns but 1 values were supplied
sqlite> INSERT INTO sampletb1 (name)
   ...> VALUES ('Suzuki');
sqlite> INSERT INTO sampletb1 (name)
   ...> VALUES ('Yoshida');
sqlite> INSERT INTO sampletb1 (name)
   ...> VALUES ('Nakata');
sqlite> SELECT * FROM samboletb1;
Error: no such table: samboletb1
sqlite> SELECT * FROM sampletb1;
1|Suzuki
2|Yoshida
3|Nakata
```

# テーブルのセレクト

```
sqlite> select * from sampletb1 limit 5;
```

# テーブルのレコード数のカウント

```
sqlite> select count(*) from sampletb1;
100
```

# レコードの削除

```
sqlite> delete from sampletb1;
```


# 現在の設定の表示

```
sqlite> .show
        echo: off
         eqp: off
     explain: auto
     headers: off
        mode: list
   nullvalue: ""
      output: stdout
colseparator: "|"
rowseparator: "\n"
       stats: off
       width:
    filename: sample1.db
```

# データベースのダンプ
.output ファイル名 で出力先をファイルに設定（空のファイルが作成されます）
.dump コマンドでデータベースをダンプします。
.output コマンドで出力先を元に戻すとファイルにフラッシュします（ファイルに書き込まれます）

```
sqlite> .output ./sample1.dump.txt
sqlite> .dump
sqlite> .output
```

---
# DB Browser for SQLite
https://github.com/sqlitebrowser/sqlitebrowser
SQLiteを操作できるビジュアルツールです。（合ってるかな？）
テーブルの中身をエクセルのように表示出来たり、SQLコマンドの入力と結果を１画面で表示出来たりして便利なツールです。

Macなら `Homebrew` でインストール出来ます。その他は良しなに。。。

## テーブルを表示

データベースファイルを開いて、テーブルを表示してみます。
こんな感じ
<img width="1264" alt="スクリーンショット 2020-03-17 8.38.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/0dbbc42c-0b89-fbac-18ac-0a2266db647e.png">


# CSVインポート シェル
CSVインポート コマンドラインシェル(2020-03-18追加）

インポート用のCSVファイルを用意して、`.import`コマンドで読み込みます。

CSVファイル
ヘッダーは取り除いたデータだけの状態にしておきます。

```
$ cat in1.csv
"Kawasaki"
"Honda"
"Toyota"
```

`INTEGER PRIMARY KEY` を持つテーブルにCSVインポートする際は、
一旦一次テーブルに読み込んだのちに、INSERT文で読み込むようにします。
最初に読み込みモードを`CSV`に設定するのを忘れずに。

```
sqlite> .mode csv
sqlite> .show
        echo: off
         eqp: off
     explain: auto
     headers: off
        mode: csv
   nullvalue: ""
      output: stdout
colseparator: ","
rowseparator: "\n"
       stats: off
       width:
    filename: sample1.db
sqlite> CREATE temp TABLE TempTable (
   ...>     name TEXT
   ...> );
sqlite> .import in1.csv TempTable
sqlite> select * from TempTable;
Kawasaki
Honda
Toyota
sqlite> INSERT INTO sampletb1 (name)
   ...> SELECT * FROM TempTable;
sqlite> select * from sampletb1;
1,Suzuki
2,Yoshida
3,Nakata
4,Kawasaki
5,Honda
6,Toyota
```

---
# CSVインポート DB Browser編
CSVインポート DB Browser(2020-03-19追加)

まず読み込むCSVファイルは下記の通り

```
$ cat sampletb2.csv
Name,Age
Kawasaki,40
Honda,55
Toyota,31
Suzuki,30
Yoshida,35
```

## そのままインポート
CSVファイルをそのままインポートすることが出来ます。
自動的にテーブルが作成されます。
ファイル名がテーブル名、ヘッダー部分がカラム名となります。

メニューから Table from CSV file を選択して
<img width="644" alt="スクリーンショット 2020-03-19 7.13.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/eb84b829-a69f-8132-3287-431d48c705ac.png">

CSVファイルを選択して、OKします。
<img width="919" alt="スクリーンショット 2020-03-19 7.14.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/6d42c844-1f2f-0f49-2cd7-4357314886ee.png">

インポート完了
<img width="908" alt="スクリーンショット 2020-03-19 7.45.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/71c83a43-f0ac-3204-0147-d61d033b15ee.png">

こんな感じで読み込まれました。型も推測されているようです。
<img width="1274" alt="スクリーンショット 2020-03-19 9.19.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214523/68fa4786-aae9-02c7-21c6-0652e4a610a5.png">


---
# CSVエクスポート DB Browser編
CSVエクスポート DB Browser(2020-07-13追加)

1. Execute SQLを開いて
2. SQL文を開いて
3. 実行します
4. 実行結果がViewに出力されます
5. Save the resuls view を選択
6. Export to CSV を選択
7. 出力設定ダイアログで出力設定して save を押下
8. 出力ファイル名を入力して save を押下



---
しばらく育てていこうと思います。:ghost:

今後の予定

* CSVインポート コマンドラインシェル(2020-03-18追加）
* CSVインポート DB Browser(2020-03-19追加)
* JOIN
* 集計
* CSV出力(2020-07-13追加)

---
# 参考

とりあえず何か１冊入門書を用意すると良いかと。
「スッキリわかるSQL入門第２版」は初級〜中級？まで使えるのかなと思います。
テーブル作成が10章と後ろの方にあるのも良いかな。

その後は、達人に学ぶSQL徹底指南書などに行くと良いかと思います。