20210416のMySQLに関する記事は5件です。

【MySQL/PostgreSQL】UNIQUE制約(一意制約)の違い

MySQL 大文字と小文字を区別しない hoge@gmail.com == Hoge@gmail.com -> true UNIQUE制約に引っかからない。 PostgreSQL 大文字と小文字を区別する hoge@gmail.com == Hoge@gmail.com -> false UNIQUE制約に引っかかる。 ポスグレのほうが制約としては正しい気がしていますが、こういう仕様らしいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SQL 実行結果を見やすく出力する

目的 SQLの実行結果をテーブル状ではなく縦に出力する方法をメモ的にまとめる 方法 実行するSQLの末尾の;の代わりに\Gをつける。 紹介 下記のようなデータが格納されたusersテーブルが存在したとする。 mysql> select * from users; +------+---------+-----------+------------+------------+ | id | name | user_flag | admin_flag | check_flag | +------+---------+-----------+------------+------------+ | 1 | admin_1 | 0 | 1 | 1 | | 2 | admin_2 | 0 | 1 | 0 | | 4 | user_2 | 1 | 0 | 0 | +------+---------+-----------+------------+------------+ 上記にselect句の実行結果を載せているが、カラムが少ないのでテーブル状でも見やすい。しかし、たくさんのカラムが存在していた場合、レコードの情報が折り返されたりして直感的にデータを確認しにくい。 実行しているSQLの末尾の;を\Gに置き換えて実行する事により下記のように出力される。 mysql> select * from users\G *************************** 1. row *************************** id: 1 name: admin_1 user_flag: 0 admin_flag: 1 check_flag: 1 *************************** 2. row *************************** id: 2 name: admin_2 user_flag: 0 admin_flag: 1 check_flag: 0 *************************** 3. row *************************** id: 4 name: user_2 user_flag: 1 admin_flag: 0 check_flag: 0 3 rows in set (0.00 sec) 各レコードの情報が縦に出力され、場合によってはこちらのほうが見やすい時がありそう。通常の出力方法と併用して都度見やすい方法で使い分けていきたい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[カラム重複によるerror]Mysql2::Error: Duplicate column name ''カラム名"

概要 ターミナルで「rails db:migrate」を入力した際に起きたerror。インターネットで調べてみるとカラムが重複していることが原因だった。 原因 db/migrateを調べるとemailカラムが重複していた qiita.rb t.string :email, null: false, default: "" t.string :email, null: false, default: "" 改善方法 rails db:rollbackでマイグレーションファイルをdownさせる →重複している内容を削除し、データを1つにする →rails db:migrateする。以上のことでerrorが改善された。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VARCHARの末尾の空白は比較時に無視される

redshiftの公式ドキュメントを読んでて知ったのですが、そうみたいです。 MySQLでも同じ挙動でした。 恥ずかしながら最近初めて知ったので、勢いで書きました。。。 以下、redshiftで検証してみます。 どういうことか こんなデータがあったとします。 > \d purchase Table "public.purchase" Column | Type | Modifiers -----------+-----------------------------+----------- date | timestamp without time zone | userid | character varying(12) | productid | character varying(12) | cnt | integer | > select * from purchase; date | userid | productid | cnt ---------------------+--------+-----------+----- 2021-01-02 00:00:00 | u006 | p002 | 3 2021-01-03 00:00:00 | u007 | p003 | 8 2021-01-02 00:00:00 | u004 | p001 | 10 2021-01-02 00:00:00 | u005 | p001 | 5 2021-01-01 00:00:00 | u001 | p001 | 3 2021-01-01 00:00:00 | u002 | p001 | 1 2021-01-01 00:00:00 | u003 | p003 | 10 2021-01-01 00:00:00 | u002 | p002 | 1 2021-01-03 00:00:00 | u008 | p001 | 2 2021-01-04 00:00:00 | u009 | p001 | 2 (10 rows) productidはvarchar(12)です。 実は、productid='p001'のうちどれかに、末尾に空白を仕込んでいます。 p001の売上個数を集計してみます。 > select productid, sum(cnt) from purchase where productid = 'p001' group by productid; productid | sum -----------+----- p001 | 23 (1 row) 特に問題なさそうです。 次は、無理やりですが、こんな感じで集計してみます。 > select 'A' || productid || 'A', sum(cnt) from purchase where productid = 'p001' group by 1; ?column? | sum -------------+----- Ap001A | 8 Ap001 A | 10 Ap001 A | 5 (3 rows) = で一つに指定してるのに?複数の値??となります。 非常に、直感に反する結果です。が、仕様です。 あと、こんなクエリ生成する場面なさそうですが、極論でいくとこんな感じです。 > select * from _tmp_purchase where productid = 'p001 '; date | userid | productid | cnt ---------------------+--------+-----------+----- 2021-01-02 00:00:00 | u004 | p001 | 10 2021-01-02 00:00:00 | u005 | p001 | 5 2021-01-01 00:00:00 | u001 | p001 | 3 2021-01-01 00:00:00 | u002 | p001 | 1 2021-01-03 00:00:00 | u008 | p001 | 2 2021-01-04 00:00:00 | u009 | p001 | 2 (6 rows) そもそも、わざわざこんな特殊な集計の仕方をしなければ気付きもしないですし、末尾の空白を意識せずに集計できて便利なシーンが多いでしょう。しかし、困るケースはありそうです。 どこで困るのか 集計する環境によって結果が変わる redshiftやMySQLのように末尾の空白を無視する環境と、そうでない環境とで、集計結果が変わってしまいますね。つらいです。 関数の結果が一意に定まらないように見えてしまう こっちの方が実害出そうですが(私もこれで気付きました)、その項目を使って別の値を出力することを想定している場合も要注意です。例えば len() で違いが出てしまいます。 > select *, len(productid) from purchase where productid = 'p001'; date | userid | productid | cnt | len ---------------------+--------+-----------+-----+----- 2021-01-02 00:00:00 | u004 | p001 | 10 | 6 2021-01-02 00:00:00 | u005 | p001 | 5 | 9 2021-01-01 00:00:00 | u001 | p001 | 3 | 4 2021-01-01 00:00:00 | u002 | p001 | 1 | 4 2021-01-03 00:00:00 | u008 | p001 | 2 | 4 2021-01-04 00:00:00 | u009 | p001 | 2 | 4 (6 rows) 同じ入力に対して関数が複数の値を返しているように感じてしまいます。 「新商品はproductidが6桁以上という決まりだから len(productid)>=6 のレコードを抽出して新商品の売り上げを分析しよう!」みたいなことを考えて集計してしまうと、痛い目を見ます。 対処法 入れる前にトリム もう、これに尽きるかと思います・・・。 各言語に、末尾の空白を除去する関数なりメソッドが用意されています。面倒でも、必ずトリムしましょう! COPY時、TRIMBLANKSする redshiftだとCOPYコマンドのオプションでありました。 ただこれだと、末尾の空白の有無が環境によって異なるという問題は解決しないので、前処理の時点でトリムを行う前提は設けておきたいですね。 おわりに ちゃんと調べられてないですが、末尾の空白を勝手に削除・無視してくれる環境は多そうです。 しかし、それを知った上で活用するのと、知らないうちに末尾の空白が削除されていた状況とでは、事故率が変わると思います。 どこかのタイミングで改めてデータを確認してみましょう!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS lambdaでMysqlを使ってみた

AWSlambdaでMysqlを使ってみた 用途としてWebAPIでデータベースの情報を閲覧したい 過去経験したことのメモ 目次 lambda関数作成 環境変数 モジュール コード ネットワーク 以上の5つのを説明していきたいと思います。 ちなみにcloud9で扱っていきます。 lambda関数作成 cloud9を作成して右の縦のタブに入みたいなマークがあります。 それを、クリックして入+ で nodejs のテンプレートapi-gateway-hello-worldを作成していきます。 環境変数 lambda では環境変数を設定できるらしいんです。 試しに変数を追記します。 追記したら lambda でみてみましょう。 exports.handler = function(event, context, callback) { console.log(event); const response = { statusCode: 200, headers: { "x-custom-header": "My Header Value", }, body: JSON.stringify({message: `Hello ${process.env.name}`}), }; callback(null, response); }; 実行結果 ローカル "body": "{\"message\":\"Hello undefined\"}" リモート "body": "{\"message\":\"Hello test\"}" ここでいうローカルとは、cloud9に環境下 のことです。 リモートは、lambdaの環境下 だと思います。 process.env は、OSの環境変数を指しているので動作環境が違えば、変数は、異なってきます。 モジュール 様々な処理を行う時、外部のライブラリーを使用することは、当たり前のように行われます。 Pythonなら pip node なら npm でインストールします。 今回は、node で進めていきます。 npm init npm i mysql 上記のコマンドを実行すれば任意にディレクトリにnode-moduleをインストールできます。 ここでインストールしたものは、デプロイ時にlambdaの環境下にいきます。 コード ここでは、lambdaのコードを作ります。 ※データベースは、あらかじめ作成していてください let mysql = require('mysql'); exports.handler = async(event, context, callback) => { let connection; connection = mysql.createConnection({ host: process.env.databaseEndpoint, user: process.env.user, password: process.env.password, database: process.env.database }); try { const data = await new Promise((resolve, reject) => { connection.connect((err) => { if (err) { console.log('error connecting: ' + err.stack); return; } console.log('success'); }); connection.query('select * from sample', function(err, rows) { if (err) { throw err; } resolve(rows); }); }); const response = { statusCode: 200, headers: { "x-custom-header": "My Header Value", }, body: JSON.stringify(data), }; connection.end(); callback(null, response) } catch (err) { callback(null, { statusCode: 400, body: err.message }) } }; 上記のコードをデプロイするとWEBAPIとしてデータベースを見ることができます。 ネットワーク はい、嘘つきました。 実は、説明した通りだとラムダにネットワークの設定がされていないはずなので、データベースに接続できないです。 以下の手順を踏んでください 関数にVPC(データベースと同一)を設定する ラムダ関数に付与されているロールにAWSLambdaVPCAccessExecutionRoleを付与 ラムダにセキュリティグループの設定を行なってください mysqlとのインバウンドルールを追加します(かってに追加される気がする) あとがき 自分の経験を元に書いているので、もしかしたら何か抜けている可能性があります。 nodejsには、サーバレスのフレームワークがあったのでlambdaを作成するのであれば、それを利用する方が、簡単かもしれないです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む