- 投稿日:2019-06-25T22:07:16+09:00
SQLでデータをNULLとする基準について
SQLでは、データに
NULL
を入れることができます。
しかし、データには数値であれば「0」、文字列であれば「空白」を入れて表現することもできます。
そこで、データをNULL
とするか、「0」や「空白」で表すかを調べて考えてみました。
NULL
にする場合
NULL
にする場合は簡単です。
基準としては、値が存在しないときにNULL
を使います。
例えば、電話番号やメールアドレスなどと存在として不明確な場合にはNULL
を使います。しかし、これが年齢や身長などと存在がはっきりとわかる場合には使えないということです。
「0」や「空白」とする場合
先ほども書いた通りに、年齢や身長などと存在がはっきりとわかる場合には「0」や「空白」を使います。(この場合は「0」ですね)
まとめ
まとめると、
- 存在として値が不明確なときは、
NULL
- はっきりと存在がわかる値のときは、「0」や「空白」
- 投稿日:2019-06-25T20:57:43+09:00
これは便利!MySQLの結果を縦表示にする方法
うちの新人が知らなかったので、
小ネタとして。。。見本用に適当にテーブルを作り、データを用意しました。
※ここでは割愛します。とりあえずSELECTで中身を見てみます。
mysql> SELECT * FROM sample; +------+----------+------------+-------+-------+-------+-------+-------+-------+-------+---------------------+---------------------+ | id | password | is_deleted | text1 | text2 | text3 | text4 | text5 | text6 | text7 | created | modified | +------+----------+------------+-------+-------+-------+-------+-------+-------+-------+---------------------+---------------------+ | 1 | test | 0 | aaa | bbb | ccc | ddd | eee | fff | ggg | 2019-06-25 20:00:00 | 2019-06-24 20:00:00 | +------+----------+------------+-------+-------+-------+-------+-------+-------+-------+---------------------+---------------------+ 1 row in set (0.00 sec)デフォルトだと横長で表示されるので、
ウィンドウのサイズによって見づらかったりします。そこで今度は;を\Gに変えます。
そうすると...mysql> SELECT * FROM sample\G *************************** 1. row *************************** id: 1 password: test is_deleted: 0 text1: aaa text2: bbb text3: ccc text4: ddd text5: eee text6: fff text7: ggg created: 2019-06-25 20:00:00 modified: 2019-06-24 20:00:00 1 row in set (0.00 sec)まとめ
このように縦に表示されて見やすくなりました。
参考
MySQL 5.6 リファレンスマニュアル
https://dev.mysql.com/doc/refman/5.6/ja/mysql-commands.html
- 投稿日:2019-06-25T18:24:10+09:00
さくらサーバー PDOがSQLSTATE[HY000] [2002] No such file or directory
いろいろ調べたけど下記を修正するだけで通った。
define('PDO_DSN','mysql:dbhost=localhost;dbname=' . DB_DATABASE);
↓
define('PDO_DSN','mysql:host=localhost;dbname=' . DB_DATABASE);
- 投稿日:2019-06-25T18:07:52+09:00
Laravelのdb:seedで1452エラーが出る
Laravelを触り始めて約一ヶ月の初心者です
つまづいたのでメモ結論としてはLaravelクエリビルダのdelete(というかMySQLのDELETE)ではauto_incrementがリセットされないという仕様が分かってなかったっていう話です
1つのUserに対して多数のItemが紐付く構造
userを削除した際はitemも削除するよう外部キーを持たせてあります2019_06_25_000000_create_item_table.phppublic function up() { Schema::create('items', function (Blueprint $table) { $table->bigIncrements('id'); $table->text('title'); $table->bigInteger('user_id')->unsigned(); $table->timestamps(); $table->foreign('user_id') ->references('id') ->on('users') ->onDelete('cascade'); }); }ユーザテーブルはLaravelデフォルトなので省略
↓こちらがseeder
UserTableSeeder.phppublic function run() { DB::table('users')->delete(); App\User::create([ 'name' => 'hoge', 'email' => 'hoge@example.com', 'password' => Hash::make('hogehoge'), ]); App\User::create([ 'name' => 'hage', 'email' => 'hage@example.com', 'password' => Hash::make('hagehage'), ]); }ItemTableSeeder.phppublic function run() { DB::table('items')->delete(); App\Item::create([ 'title' => '君という花', 'user_id' => '1', ]); App\Item::create([ 'title' => 'リライト', 'user_id' => '2', ]); }2つともseed時は一回deleteで全消ししてからデータを挿入します
一回migrate:refreshを挟まないとdb:seed出来ない問題
refreshせずにシーディングを実行すると1452エラーが出る
$ php artisan db:seed Seeding: UsersTableSeeder Seeding: ItemsTableSeeder Illuminate\Database\QueryException : SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint failsrefreshを挟むと何故か成功する
php artisan migrate:refresh
したあとにphp artisan db:seed
を再度実行$ php artisan migrate:refresh Rolling back: 2019_06_10_190034_create_items_table Rolled back: 2019_06_10_190034_create_items_table Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table Migrating: 2019_06_10_190034_create_items_table Migrated: 2019_06_10_190034_create_items_table $ php artisan db:seed [~/dev/app/gaogao_gate/likes] Seeding: UsersTableSeeder Seeding: ItemsTableSeeder Database seeding completed successfully.(逆に)なんでや…
再度db:seedを実行、やっぱり1452のエラーが出る…
UserTableを確認してみたmysql> select id from users; +----+ | id | +----+ | 3 | | 4 | +----+ 2 rows in set (0.01 sec)id途中から始まってるやんけ!
どうやらdeleteではauto_incrementに設定したidがリセットされない様子(無知並感)
既に無いuser_idをitemに与えようとして1452エラーが出ていたようですどうしよう
これ見てdeleteじゃなくてtruncate使えばええやん!と思ったけどそうでも無い様子 (1701エラーを眺めながら)
外部キーがあると使えない…だと…(rollbackもできなくなる)deleteと同時にauto_incrementを1に戻してしまえばよい
そんな都合のいいクエリは無いみたいなのでdeleteの下にSQLを1行追加
UserTableSeeder.phpDB::table('users')->delete(); DB::unprepared("ALTER TABLE users AUTO_INCREMENT = 1 ");これでとりあえず解決したみたいです?
ていうかItemSeederでuser_idを数字で与えているのがそもそもダメなのでは…
- 投稿日:2019-06-25T16:29:39+09:00
AWS AuroraをMySQL Workbenchでいじる
はじめに
AWS上のAmazon Aurora(MySQL)を
MySQL Workbenchで外からいじってみました。
Amazon Auroraとは
- AWSが提供しているフルマネージドなデータベースサービス。
- 可用性99.99%
- 最低でも3つのAZにデータを6個複製、継続的にAmazon S3にバックアップ
- MySQL、PostgreSQL互換
- いろいろ自動でやってくれる(プロビジョニングとかバックアップとか)
- ストレージが64TBまで自動で増える。
- Aurora Serverlessを使えばインスタンスの性能まで自動で管理してくれる。
詳しくはこちら
Amazon Auroraデータベースのセットアップ
AWSコンソールのRDSからいきます。
データベースの作成からAmazonAuroraを選択します。
エディションはMySQLです。接続のところの追加の接続設定で「パブリックアクセス可能」を「あり」にします
これをしないとVPC外から接続できません。
あと付与するセキュリティグループでインスタンスのポートに接続可能にしておくのも忘れずに(デフォルトだと3306)
他の設定は適当で大丈夫です。作成できたらエンドポイントをメモっておいてください。
MySQL Workbenchを起動
起動したら下の矢印の+ボタンを押します。
そしたらこの画面が出てくるので先程のエンドポイントとユーザー名、パスワードを入力してOKを押します。
スキーマの作成
接続できたらこんな画面
左上のアイコンをクリックするとスキーマが作成できます。テーブルの作成
適当にスキーマを作成したら
今度はテーブルを作成します。
右隣のボタンです。PKとかNNとかなんやっておもったら右下のStorageってところに書いてありました。
PrimaryKeyとかの設定ですね。
データ挿入
テーブルが作れたらデータの挿入です
左側のテーブル名のところにカーソルを当てると表っぽいアイコンが出てきてそれをクリックするとテーブルの中身が見えます。
真ん中らへんのEditのところでいろいろ挿入したり削除したりできます。
変更したら右下のApplyで実際のコマンドとして入力するとテーブルが更新されます。コマンドで表を操作したり、GUI上でポチポチとテーブルを操作したりできます。
すぐに反映された結果のテーブルが見えるので便利です。まとめ
Amazon AuroraをGUIのMySQLクライアントから触ってみました。
いろいろ機能が豊富そうなので研究しがいがありそうです
- 投稿日:2019-06-25T09:58:59+09:00
MySQLのデータ型について勉強したことをまとめた
実践ハイパフォーマンスMySQLを読んで考えたことをまとめました。
通常は小さい方がいい
当たり前だがデータ型が小さい方がパフォーマンスが良くなるので、なるべく小さいデータ型を使うよううにする。
しかし、この時にデータ型の大きさを過小評価すると、あとでデータ型の範囲を広げる必要が出てくる。単純なものがいい
データ型が単純であるほど、操作に時間がかからない。
例えば、日付と時刻は文字列ではなくMySQLの組み込み型として格納すべき。
IPアドレスは文字列でなく整数型で格納すべき。(.は人間が認識しやすいようにつけられているだけだから)できればNULLを使用しない
NULL値を設定できる列はインデックス、インデックス統計、値の比較を複雑にするので、それらを参照するクエリをMySQLで最適化するのは難しい。NULL値を格納できる列はより多くの記憶域を使用し、内部でも特殊な処理を要求するから。
ただし通常NULL値を格納できる列をNOT NULLにしてもパフォーマンスの向上はわずかなので、列にインデックスをつける予定がある時以外は優先しなくていい。ここのリンクにも書いてある通り、NOT NULLを使わずに例えば
''
を使うことはSQLアンチパターンとして知られているので、慎重に考える必要がありそう。
NOT NULLを使わずに''
とかでNULLを表現すると''
がNULLであることを開発者が覚えておく必要があるので、生産性を下げる原因になりうる。整数
整数型には
- TINYINT
- SMALLINT
- MEDIUMINT
- INT
- BIGINT
がある。
整数型はUNSIGNED
属性を持つことで、格納できる正の数の上限を約2倍にすることができる。実数
実数とは少数部分を持つ数字のこと。
BIGINTに収まらない大きな整数を格納するためにDECIMALを使うこともできる。不正確な型
- FLOAT
- DOUBLE
どちらも標準の浮動小数点演算の近似計算をサポートする。
それぞれの違いについては
https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html
に詳しく書いている。正確な型
DECIMAL型
http://dcx.sap.com/1201/ja/dbreference/decimal.html
記憶域と計算のコストが増えるため、財務データを格納するなど少数部分の正確な結果が必要な時だけにする
文字列型
VARCHAR型
可変長の文字列を格納する最も一般的なデータ型。
必要な記憶域しか使用しないので、固定長の型ほど多くの記憶域を使用しない。
格納する値が短ければ短いほど使用する記憶域も小さい。
VARCHAR型は値の長さを保存するために1か2バイトを使用する。CHAR型
固定長の文字列データ型。
nバイトに満たない場合は文字列の右側に空白が追加され、10バイトぴったりに調整される。BLOB型とTEXT型
BLOB型は大量のバイナリデータを格納する。
TEXT型は大量の文字列データを保存する。他のすべてのデータ型と異なり、MySQLはBLOB型とTEXT型の値を独自のIDを持つオブジェクトとして処理する。
VARCHAR型とTEXT型どちらを使うべき?
ここのサイトに詳しく書いてある。
ストレージエンジンごとに違いはあるが、TEXT型は外部記憶領域を使ってDBにはそのポインタが格納される。
一方VARCHAR型は値そのものをDB内に保存するためアクセス速度が早い。
基本的にはVARCHAR型を使った方がいい。日付と時刻型
DATETIME
1001~9999年までの値を格納することができる。精度は1秒。YYYYMMDDHHMMSS形式で整数にアンパックする。これには8バイトの記憶域が使用される。
TIMESTAMP型
1970年1月1日午前0時からの経過時間を秒数で格納する。記憶域を4バイトしか使用しないのでDATETIME型より範囲はずっと狭い(1970年から2038年の途中まで)
他のデータ型と違いTIMESTAMP型の列はデフォルトでNOT NULL。どちらを使うべき?
記憶域が小さいことを考えると基本的にTIMESTAMPだが2038年問題や特集な挙動があるようなので注意が必要。
- 投稿日:2019-06-25T00:44:42+09:00
sequelizeでモデルからENUMの値を取得する方法 [Node.js + Express]
はじめに
Node.js + Expressを使って開発を行った際に、sequelizeを使ってモデル内のカラムからENUMの値を取得した時のやり方をメモしておきます。
モデルの定義確認
以下のように簡易モデルを定義したとします。
sequelize.define('model', { animals: { type: Sequelize.ENUM, values: ['dog', 'cat', 'bird'] } })取得方法
Model.rawAttributes.states.values
でENUMの値を取得できます。var Model = sequelize.define('model', { states: { type: Sequelize.ENUM, values: ['dog', 'cat', 'bird'] } }); console.log(Model.rawAttributes.states.values); // logs ['dog', 'cat', 'bird'] in consoleカラムからENUMの値を取得する場合は、
model.column.rawAttributes.states.values
などのようにすると同様に取得可能です。