- 投稿日:2020-05-17T21:53:02+09:00
railsでmysqlでdb:createしたらAccess denied for user 'root'@'localhost'
調べると
Access denied for user 'root'@'localhost' (using password: NO)
の対処はたくさん出てくるけど、Access denied for user 'root'@'localhost'
で終わっているエラーはすぐに出てこないので自分用に残します。対処法
mysqlにユーザーを指定してログイン。
別のマシンでサーバーが動いていたら、ホスト名も指定する。
パスワード入力を求められるので、パスワードを覚えていたら入力。
間違えて何度もエラーが出るなら頭にsudo
付けたら入れる。$ mysql -u root -p任意のユーザー名とパスワードを入力する。
ここではユーザーに全てのDB操作権限を付与している。
*.*
にDBの名前を入れる。
大文字小文字区別しないので小文字でもいい。
私の場合は既存のユーザーに権限付与したので、存在しないユーザーを指定したらユーザー作成から始めないといけないかもしれない。mysql> GRANT ALL PRIVILEGES On *.* TO ユーザー名@localhost IDENTIFIED BY ‘パスワード’;このあとに
rails db:create
しても同じエラーが出たので,database.yml
を修正。
username
とpassword
に先程作成した任意のユーザー名とパスワードを入力。config/database.ymldefault: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: ユーザー名 password: パスワード socket: /var/run/mysqld/mysqld.sock development: <<: *default database: hoge_development test: <<: *default database: hoge_test production: <<: *default database: hoge_production username: hgoe password: <%= ENV['HOGE_PASSWORD'] %>$ rails db:create Created database 'hoge_development' Created database 'hoge_test'上手く行きました。
ちなみに表示されるプロンプトの意味
促す 意味 mysql> 新しいクエリの準備ができました -> 複数行クエリの次の行を待機しています '> 一重引用符(')の完了を待つ "> 二重引用符(")の完了を待つ `> バックティック(`)の完了を待つ /*> コメント(/*)の完了を待つ
- 投稿日:2020-05-17T21:25:33+09:00
MySQL 初期設定
# 起動と停止 $ mysql.server start # 起動 $ mysql.server stop # 停止 # まずは専用のユーザを作る $ mysql -u root mysql> SELECT user, host FROM mysql.user; mysql> CREATE user'tommy'@'localhost' IDENTIFIED BY '***' ; # データベースを作る mysql> show databases ; mysql> create database cate ; mysql> use cate # ユーザにデータベース捜査権限を付与する mysql> SHOW GRANTS FOR 'tommy'@'localhost' ; mysql> GRANT all ON cate.* TO 'tommy'@'localhost' ; ※ GRANT [権限] ON [適用対象のデータベース].[適用対象のテーブル] TO 'cate'@localhost IDENTIFIED BY '***'; # 専用ユーザでログインする $ mysql -u tommy -p -D cate -h 127.0.0.1 # mysql2 database.yml で utf8mb4 を指定 https://techracho.bpsinc.jp/hachi8833/2016_08_25/25044
- 投稿日:2020-05-17T19:25:26+09:00
サザエさんと学ぶSQL構文(参照クエリチートシート)
Introduction
きっかけ
データベースの勉強をしようということで、入門書を読みました。
そこでデータベースの入門書を元に、自分への備忘録としてまとめます。
しかしただ入門書と同じ実験データで話しても面白くないということで、サザエさんのキャラクターを用いて解説いたします。1要約
本稿では、SQLの基本的な参照コマンドと実行結果を画像を用いて紹介します。
<話すこと>
・SQLデータベースの操作(参照)
・SQLのデータベースの作り方
・ビューを作成する方法とメリット
に関する構文の紹介
磯野家、フグ田家の家族構成<話さないこと>2
・環境構築に関すること
・SQLデータベースの操作(集約、整列)
・サブクエリの用法
・外部結合、内部結合
・かもめ小学校のこと、伊佐坂先生についてなど自己紹介
環境情報 macOS Catalina ver:10.15.3 SQL Ver 8.0.19 for osx10.15 on x86_64 (Homebrew)対象者
・SQLの初心者の方
・1を聞いて10を理解できるエンジニア
・mysql系データベースを使いたい方
・Macユーザーの人
・サザエさんを過去見たことがある方。非対象者
・SQLが超お得意な人
・説明下手な筆者を攻撃しようとするエンジニア
・mysql以外のDBMS系データベースを使いたい方3
・Windowsユーザーの人 4
・サザエさんのファンLet's Start
1. データベースの操作方法
今回は、以下のデータベースを操作していきます。
Case1:表から列名を指定して取得します。
実際の想定例・・・
サザエさんには、どんな名前のキャラがいるのか忘れた時。SELECT name FROM Family;Family表のname列を取得します。
Case2:表から複数の列名を指定して取得します。
実際の想定例・・・
サザエさんに登場するキャラの年齢を知りたい時。SELECT name, age FROM Family;Family表のname列とage列を取得します。
Error:
複数選択するときの注意として、列名全てにコンマを付すと、エラーを吐きます。
エラー例
SELECT name, age, FROM Family;
僕も何度も苦しみました。気をつけてください!Case3:表から列名を指定して重複を除いて取得します。
実際の想定例・・・
サザエさんに登場するキャラってどんな性別があるっけ?と、気になって気になって夜も眠れないとき。SELECT DISTINCT gender FROM Family;Family表のgender列を取得します。
Case4:表から複数の列から、重複を除いて取得します。
実際の想定例・・・
サザエさんに登場するキャラが、それぞれの性別で昼間どんなことしてるのか知りたくなったとき。SELECT DISTINCT gender, category FROM Family;Family表から重複を除いてgender列とcategory列を取得します。
Case5:表から条件に該当するデータを検索して、取得します。
実際の想定例・・・
サザエさんに登場する女性キャラを、知りたくなったとき。SELECT name, gender FROM Family WHERE gender = '女';Family表からgender列が「女」という条件のname列とgender列を取得します。
Case6:表からNULLが含まれるデータを検索して、取得します。
実際の想定例・・・
サザエさんに登場するキャラのなかで、血液型がわからない人は誰なのか気になったとき。5SELECT name, blood FROM Family WHERE blood IS NULL;Family表からblood列がNULLであるname列とblood列を取得します。
Column:
NULL以外のものが知りたい時は、
SELECT name, blood FROM Family WHERE blood IS NOT NULL;
をご利用ください。Case7:表から任意の値からの大小を指定したデータを検索して、取得します。
実際の想定例・・・
サザエさんに登場するキャラのなかで、20才以上は誰なのか気になったとき。SELECT name, age FROM Family WHERE age >= 20;Family表からage列が20以上であるname列とage列を取得します。
Error:
20歳以上を記述するときに、「>=」じゃなくて、「=>」とすると、エラーを出力します。
SELECT name, age FROM Family WHERE age => 20;参考:
他の比較演算子の場合は以下のように記述します。等しいとき「=」 (20歳であるとき)
SELECT name, age FROM Family WHERE age = 20;等しくない「<>」 (20歳でないとき)
SELECT name, age FROM Family WHERE age <> 20;より大きい「>」 (20歳より大きいとき)
SELECT name, age FROM Family WHERE age > 20;以上「>=」 (20歳以上であるとき)
SELECT name, age FROM Family WHERE age >= 20;より小さい「<」 (20歳より小さいとき)
SELECT name, age FROM Family WHERE age < 20;以下「<=」 (20歳以下であるとき)
SELECT name, age FROM Family WHERE age <= 20;Case8:表から複数の条件を指定してデータを検索して、取得します。
実際の想定例・・・
サザエさんに登場するキャラのなかで、年齢が30歳に満たない男性を知りたくなったとき。SELECT name, gender, age FROM Family WHERE gender = '男' AND age < 30;Family表からgender列が「男」で、かつage列「30未満」であるname列とgender列とage列を取得します。
参考:
ほかの論理演算子の場合は以下のようになります。「または」(男性もしくは、B型でない)
SELECT name, gender, blood FROM Family WHERE gender = '男' OR blood <> 'B型';「否定」(男性でない)
SELECT name, gender FROM Family WHERE NOT gender = '男';Case9:Betweenで範囲を指定します。
実際の想定例・・・
サザエさんに登場するキャラのなかで、1900年から1910年の間に生まれたのは誰なのか気になったとき。SELECT name, birthday FROM Family WHERE birthday BETWEEN '1900-01-01' AND '1910-12-31';Family表からbirthday列が「1900-01-01」から「1910-12-31」の間にあるname列とbirthday列を取得します。
もちろん以下の記法でも大丈夫です。
SELECT name, birthday FROM Family WHERE birthday >= '1900-01-01' AND birthday <= '1910-12-31';Case10:複数の論理演算子を使用した場合の優先順位を確認します。6
実際の想定例・・・
サザエさんに登場するキャラのなかで、血液型が「不明」もしくは「A型」の女性が誰なのか、クイズで答える必要があるとき。SELECT name, gender, blood FROM Family WHERE (blood IS NULL OR blood = 'A型' ) AND gender = '女';Family表からblood列が「空白」もしくは「A型」で、かつgender列が「女」という条件のname列とgender列とblood列を取得します。
Case11:指定した文字列を含むデータを取得します。
実際の想定例・・・
サザエさんに登場するキャラのなかで、名前に「野」がつく人を知りたくなったとき。SELECT name FROM Family WHERE name LIKE '%野%';Family表からname列に「野」が含まれるname列を取得します。
参考:
「%」は、ワイルドカードと呼ばれ「任意のデータの代用」をできます。%は文字数が不明なときに、利用できます。
ワイルドカードは、他に「」があります。文字数がわからない時は、「%」を、文字数がわかる時は、「」を使い分けることで、効率よくデータを取得できます。
例えば「磯野波平」を取得したい時は、4文字ということが分かっていれば、「%」よりも「_」を使う方が効率よく検索することができます。SELECT name FROM Family WHERE name LIKE '_野__';2. もっと細かく検索したい人向け!
より細かく検索ができるように、ビューという方法があります。
Case12:特定の条件で、表を分割して名前をつける。
実際の想定例・・・
サザエさんに登場するキャラを、磯野家という家族単位で管理したい。CREATE VIEW Isonoke AS SELECT * FROM Family WHERE name LIKE '磯野%';Family表からname列に「磯野」が含まれるという条件で、全ての列を取得して、「Isonoke」という名前をつけます。
SazaesanというDBのなかに、「Family」というテーブルと「isonoke」というビューが作成されました。ビューは、大文字小文字を区別していないので、「Isonoke」で登録しても「isonoke」として登録されています。
ビューを作成することで、「磯野家」のなかで、検索するときには、いちいちWHERE句で条件を指定しなくても良い点があります。ちなみに新規のテーブルを作らず、わざわざビューを使うメリットは、元々のFamilyのデータで変更があると、ビュー側でも変更されるからです。
もちろんフグ田家も作成できますよ!
3. データベースを作る方法
自らDBを作ることになることは、あまりないと思うので、DBの作り方は、簡単に紹介します。
需要があれば加筆修正いたします。CREATE DATABASE Sazaesan; SHOW DATABASES; USE Sazaesan;CREATE DATABASEで、データベースを作成します。
今回はSazaesanとします。
SHOW DATABASEで、現在どんなデータベースがあるのかを確認できます。
USE でどのデータベースを使うのかを指定します。
実際のデータベースを触る時は、基本的にUSEされた後の状態で使用することが多いと思います。Column:
sqlは、アルファベットの大文字と小文字を区別しません。
なので、create database sazaesanもCREATE DATABASE SAZAESANも全て同じ命令ですが、入門書に書いてあった通りSQL命令を大文字表記、データベースや表の名前は先頭大文字表記、列名などは全て小文字表記として記述しています。表を作って、データを入力します。
SHOW TABLES; CREATE TABLE Family( family_id CHAR(4) NOT NULL, name VARCHAR(10) NOT NULL, gender CHAR(1) NOT NULL, birthday DATE NOT NULL, category VARCHAR(10) NOT NULL, category_id CHAR(4) NOT NULL, age INT, blood VARCHAR(3), PRIMARY KEY(family_id));Column:
それぞれの列名と列のデータ型、空白を許すか否かを定義します。
データ型は、
整数型(INT)・・・小数点以下がない数値
実数型(DOUBLE)・・・小数点以下がある数値
固定長文字列型(CHAR)・・・固定された文字数の文字列
可変長文字列型(VARCHAR)・・・任意の文字数の文字列
日付型(DATE)・・・YYYY-MM-DD形式の日付
の5種類あります。
今回のテーブルでは、実数型を除く4種類を用いました。Family表にデータを登録します。
INSERT INTO Family VALUES('F001', '磯野波平','男','1895-09-14', 'office','C001',54, NULL); INSERT INTO Family VALUES('F002', '磯野舟','女','1901-01-01', 'house','C002',48, NULL); INSERT INTO Family VALUES('F003', 'フグ田サザエ', '女', '1922-11-22', 'house', 'C002', 27, 'B型'); INSERT INTO Family VALUES('F004', '磯野カツオ', '男', '1938-01-01', 'school', 'C003', 11, 'B型'); INSERT INTO Family VALUES('F005', '磯野わかめ', '女', '1942-01-01', 'school', 'C003', 7, 'A型'); INSERT INTO Family VALUES('F006', 'フグ田マスオ', '男', '1917-01-01', 'office', 'C001', 32, 'B型'); INSERT INTO Family VALUES('F007', 'フグ田タラオ', '男', '1946-01-01', 'house', 'C002', 3, NULL);参考:
INSERT INTO テーブル名 VALUES();
今回の記事では説明していない、データをテーブルに追加するコマンドです。Family表には7つのデータを追加しています。作成できたら、確認してみます。
SELECT * FROM Family;アスタリスクは「指定しない」という意味です。
列名を指定すれば、その列だけを取得することも可能です。まとめ
サザエさんの年齢と誕生日があまりにも古くて、改めて国民的アニメの長寿さに感動いたしました。さらに驚くべきことに、サザエさんとたらちゃんは未だに一度も声優が変わっていないそうです。この記事を期にというわけでもありませんが、サザエさんをまた見てみようと思いました。
SQL関係ない付録(Appendix)
情報元
参考にした書籍
https://ja.wikipedia.org/wiki/%E3%82%B5%E3%82%B6%E3%82%A8%E3%81%95%E3%82%93%E3%81%AE%E7%99%BB%E5%A0%B4%E4%BA%BA%E7%89%A9
サザエさん一家に関してはwikipediaをはじめとしたネットメディアで調べた情報から構成しています。完全性も正確性も保証していないため、あくまでサンプルデータとしてご認識いただきたい。 ↩
需要があれば、こちらの項目も書いていこうかなと思ったり思わなかったり・・・。 ↩
SQLの文法は同じだが、SHOW DATABASES;などの部分は異なる。実際にSQLのコマンドは、ほとんど同じだがあくまで「ほとんど同じ」なので、違う部分でエラー処理に悩んだ自分の経験からそもそも対象外としている。 ↩
別にMacとWindowsの違いが、SQLに影響を及ぼすとは考えていないが、SQLのインストール系の話を飛ばしているため。 ↩
本当にどうしても気になる時は、データベースなんかよりもGoogle検索をするなり「Hey Siri!」といって聞く方が確実であるが、そんなことは野暮だ。 ↩
括弧をつけなくてもエラーが出るわけではないが、算術演算子(和算、減算、乗算、徐算)に優先順位があるように、論理演算子にも優先順位がある。「NOT > AND > OR」の順番で優先順位が高くなる。「NOT」の方が、「AND」よりも優先され、「AND」の方が、「OR」よりも優先される。予期しないエラーを出さないために、括弧で明示的に順序を決めておくほうが、スマートだ。 ↩
- 投稿日:2020-05-17T17:55:17+09:00
【Docker】GolangからMySqlへ接続してみた
やりたいこと
GolangコンテナからMySqlコンテナに接続したい!
環境
docker 19.03.8
docker-compose 1.25.5リポジトリ
https://github.com/atsugitakuya/go-mysql-docker.git
フォルダ階層
root /
├ app /
| └ main.go
├ docker /
| └ Dockerfile
└ docker-compose.yamlmain.go作成
今回はgormというORMライブラリを使って接続していく。
https://gorm.io//app/main.gopackage main import ( "fmt" "net/http" _ "github.com/go-sql-driver/mysql" "github.com/jinzhu/gorm" ) func main() { http.HandleFunc("/", index) http.ListenAndServe(":80", nil) } // mysqlのconnectionが確認できれば「DB接続成功」が表示される // 接続に失敗時はエラーメッセージを吐く func index(w http.ResponseWriter, r *http.Request) { _, err := sqlConnect() if err != nil { fmt.Fprintf(w, err.Error()) } else { fmt.Fprintf(w, "DB接続成功") } } // connetion確認func func sqlConnect() (database *gorm.DB, err error) { DBMS := "mysql" USER := "root" PASS := "golang" PROTOCOL := "tcp(mysql:3306)" DBNAME := "mysql" CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=true&loc=Asia%2FTokyo" return gorm.Open(DBMS, CONNECT) }Dockerfile作成
今回使用するgormとmysqlのdriverをインストールしている。
なんかgitがないと動かないっぽい。あとRunコマンドは少なくした方がいいが良い。
多分もっと良い方法があるはず..../docker/DockerfileFROM golang:alpine # フォルダ作成 RUN mkdir /app # 作成したフォルダ内にmain.goを配置 COPY ./app /app # 作業場所を/appに設定(main.goがある場所) WORKDIR /app # 必要ライブラリをインストール RUN apk add --no-cache git RUN go get "github.com/go-sql-driver/mysql" RUN go get -u github.com/jinzhu/gorm # main.goをbuild RUN go build -o main . # port開放 EXPOSE 80 # app開始 CMD ["/app/main"]docker-compose.yaml作成
golangとmysqlを動かすためのdocker-compose。特に説明することない。
/docker-compose.yamlversion: '3' services: golang: build: context: . dockerfile: ./docker/Dockerfile ports: - "80:80" container_name: go-sample depends_on: - mysql mysql: image: mysql environment: MYSQL_ROOT_PASSWORD: golang MYSQL_USER: golang MYSQL_PASSWORD: golang MYSQL_DATABASE: golang container_name: mysql実行し、DBの接続確認を行う
zsh# docker-compose.yamlのある階層で実行 $docker-compose up -d .... # 立ち上がったよ!メッセージが出たらOK Creating mysql ... done Creating go-sample ... donelocalhostに接続すると、「DB接続成功」が出るはず...
接続成功!!!!
意外と簡単に接続できた...さすがGoだな...
- 投稿日:2020-05-17T16:24:23+09:00
DBのスキーマとは何か?DBごとの違い
DBについて調べたり、本を読んでいると「スキーマ」という言葉を目にします。
ですが、スキーマってなんですがと改めて聞かれると、言葉が詰まったので、スキーマについて調べてみました。
DBのスキーマとは?
データの構造、性質、データベースを操作するときのルールや表現法などを定義したもの。データベースの設計図のようなものです。
3層スキーマ構造
引用:https://itmanabi.com/db-schema/外部スキーマ
概念スキーマで定義された論理データから必要なデータです。私たちが、データを取得した時のデータですね。
概念スキーマ
データベース上の論理データです。データベースに保存しているデータや、データとデータ同志の関係性の定義したものです。
内部スキーマ
概念スキーマで定義された論理データを具体的にどのようにDBMS内部に格納するかを定義したものです。
OracleDBにとってのスキーマ
スキーマをユーザが所有するオブジェクトの論理集合と定義しています。
スキーマの目的は、
- 1 つのデータベースを多数のユーザが互いに干渉することなく使用できる
- ユーザにスキーマへのアクセス権限を与えることで、セキュリティを高める
PosgrelSQLのスキーマ
引用:https://www.dbonline.jp/postgresql/schema/index1.htmlデータベースに作成されるテーブルや関数といったオブジェクトをグループ化するものと定義しています。
スキーマを使用する理由は
- 1つのデータベースを多数のユーザが互いに干渉することなく使用できるように するため。
- 管理しやすくなるよう、データベースオブジェクトを論理グループに編成するた め。
- サードパーティのアプリケーションを別々のスキーマに入れることにより、他の オブジェクトの名前と競合しないようにするため。
MySQLのスキーマ
リファレンスに明記がないので、正しくは理解できていないのですが、
他のDBのようなスキーマという概念はなく、DB=スキーマで使われるケースが多いようです。MySQL Server に関する情報
- DB名
- テーブル名
- カラムのデータ型
- アクセス権限
などを提供する「INFOMATION_SCHEMA」は存在するため、DBで共通するスキーマを存在するようです。
参考
- 投稿日:2020-05-17T13:14:15+09:00
11rep - contextパッケージでテンプレ
contextパッケージとは何か
- Context は、APIのサーバーやクライアントを使うときに、コンテキストを提供してキャンセルや、タイムアウト、値を渡したり出来る仕組み
流れ
- (*sql.DB)Begin()でトランザクションを開始
- (*sql.Tx)Commit()でコミット、(*sql.Tx)RollBack()でロールバック
package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" "context" "time" ) func main() { db, _ := sql.Open("mysql", "user:password@tcp(host:port)/dbname") ctx := context.Background() ctx, cancel := context.WithTimeout(ctx, 1*time.Second) tx, error := db.Begin() if error != nil { log.Fatal(error) return } _, err := db.ExecContext(ctx, {Query}) if err != nil { defer cancel() tx.Rollback() } else { tx.Commit() } }
- defer cancel() 上記はタイムアウトの実装
- 1秒以上かかる場合はDone
- TimeOutの設定は下記
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute具体的な利用例からcontextとは何かを説明
- Goの典型的な利用例であるWebアプリケーションを考える
- Goのサーバにおいてリクエストはそれぞれ個別のgoroutineで処理される
- そしてリクエストHandlerは新たなgoroutineを生成しバックエンドのDBや別のサーバにリクエストを投げ結果を得てユーザに対してレスポンスを返す.
最初に注意するべきはその処理に適切なTimeoutやDeadlineを設定して処理が停滞するのを防ぐことである
- 例えば別のサーバにリクエストを投げる場合にネットワークの問題でリクエストに時間がかかってしまうことは大いに考えられる.リクエストにTimeoutを設定して早めにレスポンスを返しリトライを促すべきである.
次に注意するべきは生成したgoroutineを適切にキャンセルしリソースを解放することである.(※Must)
- 例えば別のサーバにリクエストを投げる場合に適切なキャンセル処理を行わないとTimeout後もネットワークリソースが使われ続けることになる(CPUやメモリを使い続けるかもしれない)
- この場合net/httpパッケージレベルでリクエストをキャンセルするべきである.
- さらにそのgoroutineは別のgoroutineを呼び出しそれがまた別の…と呼び出しの連鎖は深くなることが考えられる
- その場合も親のTimeoutに合わせてその子は全て適切にキャンセルされリソースは解放されるべきである > contextパッケージはこのキャンセルのためのシグナルをAPIの境界を超えて受け渡すための仕組みである.ある関数から別の関数へと,親から子へと,キャンセルを伝搬させる.
参考サイト
- 投稿日:2020-05-17T11:33:47+09:00
【MySQL】データベースの作成から’rails db:migrate’まで
はじめに
DB周りの理解が弱いと感じたので、簡単なことではあるが、自分用メモで手順をまとめる。
検証環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.3 BuildVersion: 19D76
$ ruby -v ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]$ rails -v Rails 6.0.3DBの設定
(例)
config/database.ymldevelopment: <<: *default database: myapp_database_name username: username password: abcdMySQLの設定
ログイン
ターミナルにて、
MySQLにログイン mysql -u root -p ・ユーザーの作成 CREATE USER '設定したusername' IDENTIFIED BY '設定したpassword'; ・データベースの作成 CREATE DATABASE 設定したdatabase CHARACTER SET utf8; ・ユーザーにデータベースの権限を追加 GRANT ALL PRIVILEGES ON 設定したデータベース.* TO '設定したusername'; .control+c でMySQLを抜けた後に bin/rails db:migrate終わりに。
最後まで読んで頂きありがとうございます
転職の為、未経験の状態からRailsを学習しております。正しい知識を着実に身に着け、実力のあるエンジニアになりたいと考えています。継続して投稿していく中で、その為のインプットも必然的に増え、成長に繋がるかと考えています。
今現在、初心者だからといって言い訳はできないですが、投稿の内容に間違っているところや、付け加えるべきところが多々あるかと思いますので、ご指摘頂けると幸いです。この記事を読んで下さりありがとうございました。
- 投稿日:2020-05-17T07:00:57+09:00
PHPにてPDOでMySQLに接続して、複数のSQLを実行する
1つのPHPファイル内に、INSERTとSELECTのSQLを記載する方法です。
DB接続1回で複数のSQLが実行できます。
2個目のSQLでは配列$dataの値をクリアすることがポイントです。以下のソースコードは、ユーザーID登録実行画面の想定です。
前画面のユーザーID登録確認画面からユーザー名を受け取り、DB登録しています。<!DOCTYPE html> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="description" content="XXXX"> <title>XXXX</title> <link rel="stylesheet" href="/main.css"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> </head> <body> <?php //データベースの接続エラー対策 try { // POSTメソッドで前の画面の入力値を取得する $user_name=$_POST['user_name']; //データベースに接続する $dsn = 'mysql:dbname=XXXX;host=mysqlXXXX'; $user = 'XXXX'; //''内にはユーザ名を入力 $password = 'XXXX'; //''内にはパスワードを入力 $dbh = new PDO($dsn, $user, $password); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //7桁数値をランダムで生成する $user_id= rand(100000,9999999); //ランダムで生成した7桁数値の存在チェック。$user_idがDBに存在する場合、再度ランダム数値を生成する $sql ='SELECT COUNT(*) as cnt FROM XXXX_table WHERE user_id=?'; $stmt = $dbh->prepare($sql); // prepareメソッドでSQLをセット $data[] = $user_id; // 1つ目の?にセットしたいデータが入っている変数を書く $stmt->execute($data); //executeでDBへの処理要求を実行 $rec=$stmt->fetch(PDO::FETCH_ASSOC); // SQL分を使ってレコードを追加 $sql ='INSERT INTO place_data_table(place_id) VALUES (?)'; //'INSERT INTO~'を変数$sqlに格納する $stmt = $dbh->prepare($sql); // prepareメソッドでSQLをセット $data = []; // 配列$dataの値をクリア $data[] = $user_id; // 1つ目の?にセットしたいデータが入っている変数を書く $stmt->execute($data); //executeでDBへの処理要求を実行 // データベースから切断する $dbh = null; //結果を表示 print $user_name; print 'を追加しました。<br />'; } catch (Exception $e) { /* ?><pre><?= print_r($e, true); ?></pre><?php デバッグの時にはコメントアウトを外す。エラー内容、問題が発生した行番がわかる*/ print 'ただいま障害により接続できません。'; exit(); //強制終了の命令 } ?> <a href="user_list.php">戻る</a> </body> </html>