- 投稿日:2020-02-19T22:06:23+09:00
【初学者のつまずきを記録】RailsでのMySQL接続:mysql.sock問題
はじめに
RailsでのMySQL接続手順について、備忘録的にまとめようと思います。
作業自体はごく基本的な内容かと思いますが、
初学者である僕が実際につまずいたことを重点的に記載しました。
僕と同じ初学者の方のご参考の一助となればうれしいです。
後半部分ではつまずいた原因について検討してみました。※僕自身は「RailsのDBを(初めから| |後から)MySQLに変更する」を参考にしながら進めました。
前準備:MySQLを指定してRailsアプリを作成
Railsの仕様上、データベースを指定しない場合は自動的にSQLiteとなる。
$ rails new アプリ名 -d mysql作成されたconfig/database.ymlを確認。
config/database.ymldefault: &default adapter: mysql2 (略)確かにMySQLとなっていることを確認。
MySQLとの接続
手順通り接続を試みる。が、エラー発生。
$ mysql -u root ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)mysql.sockを通じての接続ができなかったとのこと。
調べてみると、mysql.sockファイル自体が存在しないことが問題らしい。
確かに、tmpフォルダ内を確認してみても存在しない。下記実行で作成。$ sudo touch /tmp/mysql.sockその上で接続を試みても同じようなエラー発生。
$ mysql -u root ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (38)そもそも、mysql.sockファイルとは何だろう?
調べてみると、サーバーとクライアントの間で通信を行う際の仲介役的な役割らしい。
ここで、MySQLサーバーを起動していないことに気づきました。
というかエラー分にもしっかりMySQL server
とありますね。MySQLサーバーを起動。
$ mysql.server start Starting MySQL .. ERROR! The server quit without updating PID file (/usr/local/var/mysql/xxxx.pid).PIDファイルがないとのお達し。
指定された場所に作成をする。$ touch /usr/local/var/mysql/xxxx.pidその上でサーバー起動を試みるも、、、
$ mysql.server start Starting MySQL .rm: /tmp/mysql.sock: Permission denied 2020-02-17T12:13:34.6NZ mysqld_safe Fatal error: Can't remove the socket file: /tmp/mysql.sock. Please remove the file manually (略)別のエラーが発生。
mysql.sockを削除しろと??
ないと言うから作ったのに。言われるがままに削除し、
どこか不本意な気持ちのまま再度サーバー起動。成功。$ mysql.server start Starting MySQL . SUCCESS! $ mysql -u root Welcome to the MySQL monitor. (略) mysql>MySQLへの接続も成功したようだ。釈然としない。
成功した理由を考えてみた
調べてみると、mysql.sockはMySQLサーバー起動時に自動的に作成されるファイルであり、
手動で作成する類のものではないらしい。
つまり、一番始めに発生した下記エラーは、mysql.sockを作成していないことが問題ではなく、
「Can't connect
:つなげない状態」であったことが問題であったと思われる。$ mysql -u root ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)よって、mysql.sockがない状態でも、
PIDファイルを作成してサーバー起動を成功させることによって(=ここでmysql.sockが自動作成され)
MySQLへの接続も成功した、、、という理解でいいのだろうか。では手動作成のmysql.sockは何が問題であったのか?
調べてみるとどうやら手動で作成したmysql.sockは権限に問題があるようだ。
検証のために再度手動でmysql.sockを作成し、
自動作成(サーバー起動時)されたmysql.sockと$ ls -l
の出力を比較してみた。#手動 -rw-r--r-- 1 root wheel 0 2 17 22:56 mysql.sock #自動作成 srwxrwxrwx 1 xxxx(ユーザー名) wheel 0 2 17 22:45 mysql.sockなるほど違う。
手動で作成された方はrootユーザーのみが書き込みの権限を持っている。
書き込みの権限がないとうまくいかないので、(参考:MySQL の設定上の考慮事項)
rootユーザー以外での実行ができない状態となっている??ならばと手動作成した上でrootユーザー権限でサーバー起動を試みてみる。
$ sudo mysql.server start Starting MySQL . ERROR! The server quit without updating PID file (/usr/local/var/mysql/xxxx.pid).だめかー。
では手動作成したものを自動作成と同じ権限に変えてみる。
これでダメな理由はないはず。$ sudo chmod 777 mysql.sock #権限を変更 $ sudo chown xxxx(ユーザー名) mysql.sock #所有者も変更 $ mysql.server start Starting MySQL . SUCCESS!成功した!
手動でmysql.sockを作成した場合でも
権限周りを調整することによりサーバー起動ができることの確認がとれました。まとめ
解決方法を色々とググりながら進めましたが、
「まずはじっくりとエラー分を解釈すること」の大切さを痛感しました。
またlinux等の知識が不足しており、後半の検証部分は気持ちとしてしこりが残っております。
(rootユーザー権限でサーバー起動できなかったあたり等)
今後の課題にするようにしたいと思います。はじめての記事投稿でしたが、思考を整理するとても良い機会となりました。
誤り・認識違い、アドバイス等ご指摘いただけましたらとてもありがたいです。
- 投稿日:2020-02-19T17:12:24+09:00
Microsoft SQL Server から MySQL(MariaDB) へテーブル移行
いろいろ方法があるらしいが、今回は練習がてら自分で作ったスクリプトで変換。
ここではテーブルを作る。
データの移行はこちら
MS SQL Server からMySQL(MariaDB) へテーブルデータ移行 - Qiita環境
移行元
- Microsoft SQL Server 2008 R2
- Windows 2003 Foundation
移行先
- MariaDB (mysql Ver 15.1 Distrib 10.1.44-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2)
- Ubuntu 18.04
元データ
CREATE TABLE [dbo].[会員]( [stid] [int] IDENTITY(1,1) NOT NULL, [会員番号] [char](10) NOT NULL, [漢字氏名] [nvarchar](255) NULL, [フリガナ] [nvarchar](255) NULL, [性別] [tinyint] NULL, [生年月日] [datetime] NULL, [入会年度] [smallint] NULL, [所属コード] [nvarchar](8) NULL, [年次] [tinyint] NULL, [種別コード] [nvarchar](5) NULL, [郵便番号] [int] NULL, [現住所] [nvarchar](255) NULL, [携帯番号] [nvarchar](50) NULL, CONSTRAINT [PK_会員1] PRIMARY KEY CLUSTERED ( [stid] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO EXEC sys.sp_addextendedproperty @name=N'MS_AggregateType', @value=-1 , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'会員', @level2type=N'COLUMN',@level2name=N'stid' GO EXEC sys.sp_addextendedproperty @name=N'MS_ColumnHidden', @value=0 , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'会員', @level2type=N'COLUMN',@level2name=N'stid' GO EXEC sys.sp_addextendedproperty @name=N'MS_ColumnOrder', @value=1 , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'会員', @level2type=N'COLUMN',@level2name=N'stid' GO EXEC sys.sp_addextendedproperty @name=N'MS_ColumnWidth', @value=-1 , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'会員', @level2type=N'COLUMN',@level2name=N'stid' GO ・ ・ ・変換スクリプト
まず、nkfで文字コードをutfにしておく。
nkf -Lu 会員.sql > 会員.sql.utf8あとは sed で
cat 会員.sql.utf8 | sed 's/[][]/`/g' | sed 's/`hogehoge`/`test`/' | sed 's/`dbo`/`test`/' | sed 's/^GO//' | sed 's/^SET ANSI_NULLS ON//' | sed 's/^SET QUOTED_IDENTIFIER ON//' | sed 's/^SET ANSI_PADDING ON//' | sed 's/^SET ANSI_PADDING OFF//'| sed 's/"dbo".//' | sed 's/IDENTITY(1,1) NOT NULL/AUTO_INCREMENT NOT NULL PRIMARY KEY/' | sed 's/^EXEC.*//' | sed '/^$/d' | sed 's/`char`/char/g'| sed 's/`nvarchar`/nvarchar/' |sed 's/`tinyint`/tinyint/'| sed 's/`datetime`/datetime/' |sed 's/`smallint`/smallint/'| sed 's/`int`/int/' |sed 's/"/`/g' | sed '/^ CONSTRAINT/,/^) ON /d' | sed '$s/.$/)/' > 会員.mysql↑はワンライナーで行ったもの。改行を入れたもの↓。
cat 会員.sql.utf8 | \ sed 's/[][]/`/g' | \ sed 's/`hogehoge`/`test`/' | \ sed 's/`dbo`/`test`/' \ sed 's/^GO//' | \ sed 's/^SET ANSI_NULLS ON//' | \ sed 's/^SET QUOTED_IDENTIFIER ON//' | \ sed 's/^SET ANSI_PADDING ON//' | \ sed 's/^SET ANSI_PADDING OFF//'| \ sed 's/"dbo".//' | \ sed 's/IDENTITY(1,1) NOT NULL/AUTO_INCREMENT NOT NULL PRIMARY KEY/' | \ sed 's/^EXEC.*//' | \ sed '/^$/d' | \ sed 's/`char`/char/g'| \ sed 's/`nvarchar`/nvarchar/' | \ sed 's/`tinyint`/tinyint/'| \ sed 's/`datetime`/datetime/' | \ sed 's/`smallint`/smallint/'| \ sed 's/`int`/int/' |sed 's/"/`/g' | \ sed '/^ CONSTRAINT/,/^) ON /d' | \ sed '$s/.$/)/' | \ > 会員.mysql会員.mysqlができる
CREATE TABLE `test`.`会員`( `stid` int AUTO_INCREMENT NOT NULL PRIMARY KEY, `会員番号` char(10) NOT NULL, `漢字氏名` nvarchar(255) NULL, `フリガナ` nvarchar(255) NULL, `性別` tinyint NULL, `生年月日` datetime NULL, `入会年度` smallint NULL, `所属コード` nvarchar(8) NULL, `年次` tinyint NULL, `種別コード` nvarchar(5) NULL, `郵便番号` int NULL, `現住所` nvarchar(255) NULL, `携帯番号` nvarchar(50) NULL)これをmysql(MariaDB)から
MariaDB [test]> source 会員.mysqlでOK.
- 投稿日:2020-02-19T17:12:24+09:00
Microsoft SQL Server から MySQL へテーブル移行
いろいろ方法があるらしいが、今回は練習がてら自分で作ったスクリプトで変換。
元データ
CREATE TABLE [dbo].[会員]( [stid] [int] IDENTITY(1,1) NOT NULL, [会員番号] [char](10) NOT NULL, [漢字氏名] [nvarchar](255) NULL, [フリガナ] [nvarchar](255) NULL, [性別] [tinyint] NULL, [生年月日] [datetime] NULL, [入会年度] [smallint] NULL, [所属コード] [nvarchar](8) NULL, [年次] [tinyint] NULL, [種別コード] [nvarchar](5) NULL, [郵便番号] [int] NULL, [現住所] [nvarchar](255) NULL, [携帯番号] [nvarchar](50) NULL, CONSTRAINT [PK_会員1] PRIMARY KEY CLUSTERED ( [stid] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO EXEC sys.sp_addextendedproperty @name=N'MS_AggregateType', @value=-1 , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'会員', @level2type=N'COLUMN',@level2name=N'stid' GO EXEC sys.sp_addextendedproperty @name=N'MS_ColumnHidden', @value=0 , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'会員', @level2type=N'COLUMN',@level2name=N'stid' GO EXEC sys.sp_addextendedproperty @name=N'MS_ColumnOrder', @value=1 , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'会員', @level2type=N'COLUMN',@level2name=N'stid' GO EXEC sys.sp_addextendedproperty @name=N'MS_ColumnWidth', @value=-1 , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'会員', @level2type=N'COLUMN',@level2name=N'stid' GO ・ ・ ・変換スクリプト
まず、nkfで文字コードをutfにしておく。
nkf -Lu 会員.sql > 会員.sql.utf8あとは sed で
cat 会員.sql.utf8 | sed 's/[][]/`/g' | sed 's/gaku2009_cs/test/' | sed 's/^GO//' | sed 's/^SET ANSI_NULLS ON//' | sed 's/^SET QUOTED_IDENTIFIER ON//' | sed 's/^SET ANSI_PADDING ON//' | sed 's/^SET ANSI_PADDING OFF//'| sed 's/"dbo".//' | sed 's/IDENTITY(1,1) NOT NULL/AUTO_INCREMENT NOT NULL PRIMARY KEY/' | sed 's/^EXEC.*//' | sed '/^$/d' | sed 's/`char`/char/g'| sed 's/`nvarchar`/nvarchar/' |sed 's/`tinyint`/tinyint/'| sed 's/`datetime`/datetime/' |sed 's/`smallint`/smallint/'| sed 's/`int`/int/' |sed 's/"/`/g' | sed '/^ CONSTRAINT/,/^) ON /d' | sed '$s/.$/)/' | sed 's/`dbo`/`test`/' > 会員.mysql会員.mysqlができる
CREATE TABLE `test`.`会員`( `stid` int AUTO_INCREMENT NOT NULL PRIMARY KEY, `会員番号` char(10) NOT NULL, `漢字氏名` nvarchar(255) NULL, `フリガナ` nvarchar(255) NULL, `性別` tinyint NULL, `生年月日` datetime NULL, `入会年度` smallint NULL, `所属コード` nvarchar(8) NULL, `年次` tinyint NULL, `種別コード` nvarchar(5) NULL, `郵便番号` int NULL, `現住所` nvarchar(255) NULL, `携帯番号` nvarchar(50) NULL)これをmysqlから
MariaDB [test]> source 会員.mysqlでOK.
- 投稿日:2020-02-19T16:34:27+09:00
laradoc環境作成でmysql接続でつまずいた話
laradock環境にて::ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'
事象
php artisan migrate上記コマンドを流すと、タイトルのエラーが発生。。。
いやぁまいったな。。。。
とりあえずググるか。。。
某記事1 DB_HOST=localhostとしてください。
ふむふむやってみよう。。。
数十秒後
できねぇな、、、
某記事2 DB_HOST=127.0.0.1としてください。
ほんとか。。!?
数十秒後
やっぱりできんやないかい。。。
解決策
どうやら立ち上がっているコンテナに紐付けられている
HOSTにしなければいけないみたい。。。
なるほどね。
ってことで下記手順プロジェクト配下で
docker-compose exec mysql /bin/bash下記で一番下に出てきたIPをDB_HOSTに記載!
cat /etc/hostsんで改めてmigrateコマンド実行するとうまくいきました!!!
いやぁまいったね。。。
- 投稿日:2020-02-19T15:55:00+09:00
ナイーブツリーにおける任意階層にある複数ノード配下の末端ノードを1クエリで全て取得する
目的
- ナイーブツリーで構成されている多階層テーブルにおいて
- 任意の階層に所属しているノード群(= 親ノード)に所属している末端ノードの一覧を
- 親ノードとの関連が分かるように
- 1クエリで
取得したい。
つまり
親ノードid 末端ノードid 3 20 3 21 3 22 4 25 4 26 4 27 みたいな結果を取得したい。
環境
MySQL 8~
MySQLだと8系以降でしか再帰クエリが使えないため。
他DBMSでも再帰クエリが使えれば同じことはできるはず。多分。前提のテーブル構造
tableName: naive_tree
id parent_id depth is_leaf プライマリ 親id 階層 末端ノードならtrue 再帰クエリについて
ざっくり。
-- ここから再帰クエリ。`temporary_table_name`という名前で、hoge, fuga, piyo, ...の構造を持つ一時的なテーブルを作成する WITH RECURSIVE <temporary_table_name> (<hoge>, <fuga>, <piyo>, ...) AS ( -- ここから非再帰項 -- 最初に実行され、再帰項を実行するベースデータを取得する SELECT <hoge>, <fuga>, <piyo>, ... -- 上記で定義したものと同じ構造である必要がある -- ここまで非再帰項 UNION ALL -- 非再帰項と再帰項それぞれで取得できた結果をつなげる -- ここから再帰項 -- 非再帰項の取得結果をベースに実行される SELECT <hoge>, <fuga>, <piyo>, ... -- 上記で定義したものと同じ構造である必要がある FROM <temporary_table_name> WHERE <condition> -- 一時テーブル自身(temporary_table_name)を使う -- ここまで再帰項 ) -- ここまで再帰クエリ SELECT * FROM temporary_table_nameクエリ
SET @target_parent_depth = 1; -- 階層数を指定 WITH RECURSIVE tree(id, parent_id, depth, is_leaf, target_depth_parent_id) AS ( -- 指定された階層のレコードを全て取得 -- 自分自身が親なのでtarget_depth_parent_idは0としておく SELECT id, parent_id, depth, is_leaf, 0 as target_depth_parent_id FROM naive_tree WHERE id IN ( SELECT n.id FROM naive_tree n WHERE n.depth = @target_parent_depth ) UNION ALL SELECT n2.id, n2.parent_id, n2.depth, n2.is_leaf, ( CASE WHEN n2.depth = @target_parent_depth + 1 THEN n2.parent_id ELSE t.target_depth_parent_id END ) as target_depth_parent_id -- ここがキモ -- JOINされたレコードが非再帰項で取得された階層の「次の」階層だった場合には、JOINされた側のレコードが持つparent_idを使う。 -- それ以外のケースでは、JOIN元のレコードのtarget_depth_parent_idをそのまま使う。 FROM tree t INNER JOIN naive_tree n2 ON t.id = n2.parent_id ) SELECT t.id, t.target_depth_parent_id FROM tree t WHERE t.is_leaf = 1 AND target_depth_parent_id != 0 -- 末端ノードであり、かつ親レコードではないことを条件とする
- 投稿日:2020-02-19T15:31:05+09:00
【MySQL】改行を取り除く
はじめに
DBのレコード中に改行が含まれていると、コンソール上で見た時に以下のようにずれて表示されてしまい、とても見づらくなります。
このようにコンソールで見る場合は「見づらい」だけで済みますが、改行が含まれるレコードをCSVとしてエクスポートした場合はCSVのフォーマットが崩れてしまうため、エクスポートした後に改行を取り除く処理を入れることになって手間がかかります。
mysql> SELECT id, name, note FROM nkojima.user; +----+----------+----------------------------+ | id | name | note | +----+----------+----------------------------+ | 1 | nkojima | Hello,world! | | 2 | nkojima2 | Hello,world! Hello,world! | +----+----------+----------------------------+ 2 rows in set (0.01 sec)使用した環境
- OS
- CentOS-7.7
- DB
- MySQL-8.0.19
改行を取り除く方法
以下のように
REPLACE
関数を用いると、改行コードを除去した結果が簡単に得られます。
以下の例では改行コードを空文字と置き換えて単純に除去しただけですが、例えば|
など他の文字に置き換えることも可能です。また、「あるカラムの先頭もしくは末尾に改行コードがある」というケースであれば、代わりに
TRIM
関数を使うことも出来ると思いますが、汎用性が高いREPLACE
関数を覚えておけば良いと思います。mysql> SELECT id, name, REPLACE(note, '\n', '') FROM nkojima.user; +----+----------+---------------------------+ | id | name | REPLACE(note, '\n', '') | +----+----------+---------------------------+ | 1 | nkojima | Hello,world! | | 2 | nkojima2 | Hello,world! Hello,world! | +----+----------+---------------------------+ 2 rows in set (0.00 sec)参考URL
- 投稿日:2020-02-19T15:31:05+09:00
【MySQL】レコード中の改行を取り除く
はじめに
DBのレコード中に改行が含まれていると、コンソール上で見た時に以下のようにずれて表示されてしまい、とても見づらくなります。
このようにコンソールで見る場合は「見づらい」だけで済みますが、改行が含まれるレコードをCSVとしてエクスポートした場合はCSVのフォーマットが崩れてしまうため、エクスポートした後に改行を取り除く処理を入れることになって手間がかかります。
mysql> SELECT id, name, note FROM nkojima.user; +----+----------+----------------------------+ | id | name | note | +----+----------+----------------------------+ | 1 | nkojima | Hello,world! | | 2 | nkojima2 | Hello,world! Hello,world! | +----+----------+----------------------------+ 2 rows in set (0.01 sec)使用した環境
- OS
- CentOS-7.7
- DB
- MySQL-8.0.19
改行を取り除く方法
以下のように
REPLACE
関数を用いると、改行コードを除去した結果が簡単に得られます。
以下の例では改行コードを空文字と置き換えて単純に除去しただけですが、例えば|
など他の文字に置き換えることも可能です。また、「あるカラムの先頭もしくは末尾に改行コードがある」というケースであれば、代わりに
TRIM
関数を使うことも出来ると思いますが、汎用性が高いREPLACE
関数を覚えておけば良いと思います。mysql> SELECT id, name, REPLACE(note, '\n', '') FROM nkojima.user; +----+----------+---------------------------+ | id | name | REPLACE(note, '\n', '') | +----+----------+---------------------------+ | 1 | nkojima | Hello,world! | | 2 | nkojima2 | Hello,world! Hello,world! | +----+----------+---------------------------+ 2 rows in set (0.00 sec)参考URL
- 投稿日:2020-02-19T13:47:58+09:00
PHPでプレースホルダを使ったフォーム作成
PHPでフォーム作成
以前の記事で、DVWAでは変数をSQL文にそのままいれたことから、SQLインジェクションが可能なコードとなってしまっていました。
そこで今回は、そんなSQLインジェクションに対処するための方法として、プレースホルダについて紹介したいと思います。
プレースホルダとは?
プレースホルダはその名の通り、SQL文に対して後から値をセットするための場所を確保する機能となっています。
プレースホルダは、疑問符プレースホルダの?、名前付きプレースホルダの:値、で表現されまます。
また、後から入れる値のバインド値のことを、プリペアドステートメント(予約文)と言います。
このプレースホルダを使うことによって、入力値から直接SQLインジェクションが行われることを、回避できるというわけです。
HTML/PHP/MySQLでフォーム作成
ここでは、実際にフォームを作成し、プレースホルダを使うコードについて記載していきたいと思います。
コードは下記の記事を参考にしています。
https://noumenon-th.net/programming/2016/01/18/mysql-2/前提条件
- PHP 5.46
- MySQL 14.14
MySQLでDB、テーブル、カラムの設定
まずは、MySQLでDBとテーブルとカラムをセットしていきます。
ここではDBをtest1、テーブルをname_list、カラムをid・nameでセットします。
# mysql -u root -p mysql> CREATE DATABASE test1; mysql> USE test1; mysql> CREATE TABLE name (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,name TEXT NOT NULL) DEFAULT CHARACTER SET=utf8;フォームのHTMLファイルを作成
まず基本となる簡単な、フォームをHTMLで記載していきます。
index.html<!DOCTYPE html> <html> <head> <title>データを入力する</title> <meta charset="utf-8"> </head> <body> <h1>フォーム画面</h1> <form action="form.php" method="post"> 名前を入力:<input type="text" name="name"> <input type="submit" value="登録する"> </form> </body> </html>フォーム情報を登録するPHPファイル作成
次に、フォーム情報をMySQLに登録するPHPファイルを作成していきます。
SQL文はプレースホルダを使って表示していきます。
form.php<?php header("Content-type: text/html; charset=utf-8"); //データベース接続 $server = "IPアドレス"; $userName = "MySQLのユーザー名"; $password = "MySQLのパスワード"; $dbName = "test1"; $mysqli = new mysqli($server, $userName, $password, $dbName); if ($mysqli->connect_error){ echo $mysqli->connect_error; exit(); }else{ $mysqli->set_charset("utf-8"); } if(empty($_POST)) { echo "<a href='index.php'>index.php</a>←登録はこのページから"; }else{ //名前入力判定 if (!isset($_POST['name']) || $_POST['name'] === "" ){ echo "名前が入力されていません。"; }else{ //プリペアドステートメントの設定(SQL文を最初に用意して、その後はクエリ内のパラメーターの値だけを変更する) $stmt = $mysqli->prepare("INSERT INTO name_list (name) VALUES (?)"); if($stmt){ //プレースホルダに値を設定する、bind_paramsの第一引数は文字列が入るので's' $stmt->bind_param('s', $name); $name = $_POST['name']; //登録する名前をhtml表記、クオテーションを取った状態で表示 if($stmt->execute()){ echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8')."さんを登録しました"; }else{ echo $stmt->errno . $stmt->error; } $stmt->close(); }else{ echo $mysqli->errno . $mysqli->error; } } } // データベース切断 $mysqli->close(); ?>実際にはこんな感じに動作します。
これで、プレースホルダを利用したPHPのフォーム作成は完了です。
- 投稿日:2020-02-19T12:33:56+09:00
MySQL8でrootのパスワード忘れた?
Mysql8のインストール作業をしていたのですが、
rootでログインできず、パスワード忘れ?メモ間違えた?
みたいになり対処したのでメモします。my.cnfの一番下にskip-grant-tablesを追加
パスワードを入力しなくでもログインできるように、my.cnfにskip-grant-tablesを追加します。
sudo vi /etc/my.cnf [mysqld] . . skip-grant-tables再起動
systemctl restart mysqld.serviceパスワード入力なしでログインする
mysql -u rootパスワード入力しなくてもログインできるようにする
mysql> use mysql mysql> UPDATE user SET authentication_string=null WHERE user='root'; mysql> flush privileges; mysql> quitskip-grant-tablesを無効にする
sudo vi /etc/my.cnf [mysqld] . . #skip-grant-tables再起動してパスワード入力なしでログインしてみる
systemctl restart mysqld.service mysql -u root -pこれでログインできればOKなので、
あとmysql_secure_installationなどで再設定する。こちらの記事を参考にさせて頂きました。
- 投稿日:2020-02-19T12:33:56+09:00
MySQL8でrootのパスワード忘れてしまったので対処
Mysql8のインストール作業をしていたのですが、
rootでログインできず、パスワード忘れ?メモ間違えた?
みたいになり対処したのでメモします。my.cnfの一番下にskip-grant-tablesを追加
パスワードを入力しなくでもログインできるように、my.cnfにskip-grant-tablesを追加します。
sudo vi /etc/my.cnf [mysqld] . . skip-grant-tables再起動
systemctl restart mysqld.serviceパスワード入力なしでログインする
mysql -u rootパスワード入力しなくてもログインできるようにする
mysql> use mysql mysql> UPDATE user SET authentication_string=null WHERE user='root'; mysql> flush privileges; mysql> quitskip-grant-tablesを無効にする
sudo vi /etc/my.cnf [mysqld] . . #skip-grant-tables再起動してパスワード入力なしでログインしてみる
systemctl restart mysqld.service mysql -u root -pこれでログインできればOKなので、
あとmysql_secure_installationなどで再設定する。こちらの記事を参考にさせて頂きました。
- 投稿日:2020-02-19T11:15:52+09:00
ActiveRecord::PendingMigrationErrorの解決方法
1.エラーメッセージの内容
2.エラーの原因
エラーの理由はmigrateし忘れてますよというものです。
考えられる理由は下記の3つです1.単純にrails db:createのあとrails db:migrateし忘れている
2.すでにmigrationが完了している(up)状態でマイグレーションファイルを更新しrails db:migrateしてしまった
3.マイグレーションファイルの中に入れた外部参照キーが参照するテーブルがない状態でrails db:creatしてしまった(マイグレーションファイルの記述に誤りがある)3.エラーの解決方法
1.単純にrails db:createのあとrails db:migrateし忘れている
マイグレーション実行の下記のコマンドを打ち込みましょう
$ rails db:migrate2.すでにmigrationが完了している(up)状態でマイグレーションファイルを更新しrails db:migrateしてしまった
方法1 既存のテーブルを全削除し、再度マイグレーションの状態をupにする下記のコマンドを打ち込みましょう
$ rails db:migrate:reset方法2 マイグレーションの最新のものだけ実行を取りやめて編集可能(down)にするコマンドrails db:rollbackののち、マイグレーションファイルの更新コマンドrails db:migrateを打ちましょう
$ rails db:rollback $ rails db:migrate※方法1と方法2の違いは処理速度(工程)の量の違いです。テーブルの数が多い場合は方法2としましょう。テーブルが数十程度なら方法1でも2でも大差はありません
※マイグレーションの状態を調べるコマンドは下記の通りです
$ rails db:migrate:status3.マイグレーションファイルの中に入れた外部参照キーが参照するテーブルがない状態でrails db:creatしてしまった
①-1外部参照されるマイグレーションファイルを作成し、app/modelの中のファイルにアソシエーションを追記(または修正)する
①-2マイグレーションファイルから不必要な外部参照キーを消す②上記①のどちらかの修正のあとに下記コマンドを打ち込みましょう
$ rails db:migrate:reset4.すでにデータベースにレコードを入れてしまい、それを残したまま修正する方法(補足)
新たに追加したい項目のテーブルを作成し、本来追加したかったテーブルのidを外部キーとする方法をとりましょう。
- 投稿日:2020-02-19T11:03:43+09:00
RubyのMysql2の各種情報(バージョン情報やオプション)を取得する方法
背景
Ruby on Rails 等で MySQLを利用している時、低レイヤーの根深い問題や、よくわからないエラーに遭遇したことはありますでしょうか?
RubyでMySQLを利用する際によく使われるライブラリである
Mysql2
では、C拡張を利用してlibmysqlclient
とリンクし、データベースサーバ上のmysqld
に対してアクセスしている都合上、複数の概念に対してのバージョン情報やオプションを扱う必要があります。これらのバージョン情報は、問題の原因究明に重要であるため、取得方法を知っておくことで、効率的な作業が可能になります。自分が調べる時は勿論、他の人に手伝ってもらう時にも重要なヒントになります。
TL; DR
以下のようなデータを記録しておくと、調査が捗ります。
# Railsの場合の Mysql2::Client のオブジェクトの取得方法の例 client = ActiveRecord::Base.connection.raw_connection # 自前の場合の Mysql2::Client のオブジェクトの作成方法の例 client = Mysql2::Client.new(host: 'localhost', username: 'root') puts JSON.pretty_generate( 'RUBY_DESCRIPTION' => RUBY_DESCRIPTION, # Rubyの詳細 'Mysql2::VERSION' => Mysql2::VERSION, # gemのバージョン 'Mysql2::Client#info' => client.info, # libmysqlclient のバージョン 'Mysql2::Client#server_info' => client.server_info, # 接続先の MySQL Server のバージョン ) # 接続に関するオプション (おまけ) puts JSON.pretty_generate(client.query_options.reject { |k, _v| k == :password }) # 他にも重要な情報はあるが、最低限、パスワードは取り除く出力例
{ "RUBY_DESCRIPTION": "ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin18]", "Mysql2::VERSION": "0.4.10", "Mysql2::Client#info": { "id": 80016, "version": "8.0.16", "header_version": "8.0.16" }, "Mysql2::Client#server_info": { "id": 50637, "version": "5.6.37" } }各種バージョン
Rubyの詳細情報
ruby -v
の詳細が記述されます。https://docs.ruby-lang.org/ja/latest/method/Object/c/RUBY_DESCRIPTION.html
gem のバージョン
gem のバージョンは、以下の Mysql2 自体のバージョン
Mysql2::VERSION
になります。https://github.com/brianmario/mysql2
コードは以下のような形になっています。
module Mysql2 VERSION = "0.5.3".freeze endlibmysqlclient のバージョン
Mysql2 は、独自に MySQLサーバ との通信プロトコルを実装しているわけではなく、 MySQLの提供している、Cで書かれたクライアントライブラリを利用してアクセスしています。
この時のライブラリのバージョンによって、微妙な挙動の差異が発生する場合があるので、この情報も重要です。Mysql2 では、以下のようにC拡張で
Mysql2::Client#info
が実装されています。version = rb_str_new2(mysql_get_client_info());これが呼び出している
mysql_get_client_info()
が何を返すかは、MySQLのドキュメントに記述されています。https://dev.mysql.com/doc/refman/5.6/en/mysql-get-client-info.html
Returns a string that represents the MySQL client library version (for example, "5.6.48").
ということで、クライアントライブラリ
libmysqlclient
のバージョンが返却されます。接続先の MySQL Server のバージョン
問題が発生した時は、クライアントバージョンは勿論ですが、相手側のサーババージョンも気になるところです。
Mysql2 では、以下のようにC拡張で
Mysql2::Client#server_info
が実装されています。server_info = rb_str_new2(mysql_get_server_info(wrapper->client));これが呼び出している
mysql_get_server_info()
が何を返すかは、MySQLのドキュメントに記述されています。https://dev.mysql.com/doc/refman/5.6/en/mysql-get-server-info.html
Returns a string that represents the MySQL server version (for example, "5.6.48").
ということで、接続先の MySQL サーバのバージョンが返却されます。
接続に関するオプション
MySQLのサーバ側で設定されているオプションも勿論大切ですが、各クライアント(コネクション)毎に維持されているオプションも、細かい挙動を知る上では重要になってきます。
Mysql2 では、以下のようにインスタンス変数へのアクセッサーが生やされて、
Mysql2::Client#query_options
があるので、それを利用する形が良いと思われます。※ このアクセッサーにはパスワードを含む情報が格納されているので、情報共有の際には、それをしっかり取り除くことを留意しておいてください。
参考
https://github.com/brianmario/mysql2
https://dev.mysql.com/doc/refman/5.6/en/c-api-server-client-versions.html