MySQLで数値の切り上げをする

TRUNCATEを使うことで切り捨てになるので、これを応用して0.9を足して切り捨てさせることで切り上げとする。下記は一ページに100件に表示をして、残りはページャーで処理したいので、何ページにページを分割すればいいかを計算するSQLの例。

SELECT TRUNCATE(COUNT(*)/100+0.9, 0) AS page_num FROM item;

参考
https://www.softel.co.jp/blogs/tech/archives/2570/comment-page-1

MySQLでSELECTした結果をINSERTしようとしたらNULLが空白になった

こんなテーブルがありました。PRIMARY KEYにNULLが設定されようとしています。MySQLにおいて、PRIMARY KEYが設定されたカラムは、NULLが不可です。

mysql> CREATE TABLE `case1` (
->   `hoge` VARCHAR(20) DEFAULT NULL,
->   `hoge2` VARCHAR(20) DEFAULT NULL,
->   PRIMARY KEY (`hoge`,`hoge2`)
-> );
Query OK, 0 rows affected (0.01 sec)

通常は下記のようにPRIMARY KEYにNULLを入れようとしても。ぶつかって止まってくれます。

mysql> INSERT INTO case1 (hoge, hoge2) VALUES ("hoge", NULL);
ERROR 1048 (23000): Column 'hoge2' cannot be null

しかし下記のようにしてSELECT結果をINSERTしようとしている場合は

mysql> INSERT INTO case1 (hoge, hoge2) SELECT "hoge2" AS hoge, NULL AS hoge2;
Query OK, 1 row affected, 1 warning (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 1

NULLが空白に変換されて保存されてしまいました。こういう動きをするの初めて知りました。

mysql> SELECT * FROM case1;
+-------+-------+
| hoge  | hoge2 |
+-------+-------+
| hoge2 |       |
+-------+-------+
1 row in set (0.00 sec)

ちなみに今回のはPRIMARY KEYにNULLが設定されているのが問題でSELECTした結果を保存しようとすることが問題ではないです。試しにこのようなテストを実行すると。

CREATE TABLE `case2` (
`hoge` VARCHAR(20) NULL,
`hoge2` VARCHAR(20) NULL,
PRIMARY KEY (`hoge`)
);
INSERT INTO case2 (hoge, hoge2) VALUES ("hoge", NULL);
INSERT INTO case2 (hoge, hoge2) SELECT "hoge2" AS hoge, NULL AS hoge2;
mysql> CREATE TABLE `case2` (
->   `hoge` VARCHAR(20) NULL,
->   `hoge2` VARCHAR(20) NULL,
->   PRIMARY KEY (`hoge`)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO case2 (hoge, hoge2) VALUES ("hoge", NULL);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO case2 (hoge, hoge2) SELECT "hoge2" AS hoge, NULL AS hoge2;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0
mysql> SELECT * FROM case2;
+-------+-------+
| hoge  | hoge2 |
+-------+-------+
| hoge  | NULL  |
| hoge2 | NULL  |
+-------+-------+
2 rows in set (0.00 sec)

想定通りに保存されました。てっきりSELECT結果をINSERTする時NULLは使えないパラレルワールドに来たのかと思いましたよ。

他人のサーバーのmysql.sockの場所を調べる

自分が用意した環境だったりしたら記憶にございだと思うが、そうではない他人の環境で、musqlコマンドがデフォルトで使うmysql.sockの位置がどこか分からない時に調べる方法の一つしてDBから確認することができる。

mysql> SHOW VARIABLES LIKE '%sock%';
+-----------------------------------------+---------------------------+
| Variable_name                           | Value                     |
+-----------------------------------------+---------------------------+
| performance_schema_max_socket_classes   | 10                        |
| performance_schema_max_socket_instances | -1                        |
| socket                                  | /var/lib/mysql/mysql.sock |
+-----------------------------------------+---------------------------+
3 rows in set (0.00 sec)

mysqldumpでCouldn’t executeと言われた時の対策

下記のようなmysqldumpコマンドを実行したところ

mysqldump -h database -u hoge hoge2 -phoge3 --skip-lock-tables --default-character-set=utf8mb4 hoge4 hoge5 > ~/Downloads/hoge6.sql

下記のようなエラーが出た

mysqldump: Couldn't execute 'SELECT COLUMN_NAME,                       JSON_EXTRACT(HISTOGRAM, '$."number-of-buckets-specified"')                FROM information_schema.COLUMN_STATISTICS                WHERE SCHEMA_NAME = 'hoges' AND TABLE_NAME = 'item';': Unknown table 'COLUMN_STATISTICS' in information_schema (1109)

解決にはmysqldumpコマンドに--column-statistics=0オプションを追加すれば良い

mysqldump -h database -u hoge hoge2 -phoge3 --skip-lock-tables --default-character-set=utf8mb4 --column-statistics=0 hoge4 hoge5 > ~/Downloads/hoge6.sql

今回このエラーが出た時のmysqldumpのバージョンは下記で、サーバー側のMySQLのバージョンは変更せずおきました。

$ mysqldump -V
mysqldump  Ver 8.0.11 for osx10.13 on x86_64 (Homebrew)

参考

Macで立ち上げたDockerコンテナに外部からアクセスできないようにする

Dockerはコンテナ立ち上げるとコンテナ丸出しだったりする。

  • 業務用のサービスをローカルで立ち上げて動作確認しているが他の人に見られたらまずいから遮断したい(アルバイトとか違う部署とかわからないけど万が一見られて抜かれたらまずいとか、そもそもコワーキングスペースみたいなWi-Fi共有してますみたいなケース?)
  • 仕事中に自分の趣味のWebサイトをDockerコンテナで立ち上げてサボってる事を他の社員に知られる可能性を消したいとか?

などなどの理由で遮断したい時は簡単でファイアウォールですべてをブロックが一番シンプル。Macでポートごとに遮断する方法など教えてもらえると嬉しいです。

スクリーンショット 2018-07-04 13.33.41.png

JavaScriptでCookieをすべて削除する

これをブックマークレットに仕込んでおけば、Cookieを利用したアプリケーションでいちいちブラウザのCookieを削除しなくてもいい。

document.cookie.split(";").forEach(function(cookie) {
var date = new Date();
date.setDate(date.getDate() - 1);
document.cookie = cookie.trim().replace(/=.*/, "=;expires=" + date.toUTCString() + "/");
});