- 投稿日:2020-09-22T19:40:32+09:00
Docker x Laravel phpMyAdmin を導入する
以前の記事(最強のLaravel開発環境をDockerを使って構築する【新編集版】)のコメントにてphpMyAdminを使用したいという要望がありましたので補足の記事を作成させていただきます。
手順
https://github.com/ucan-lab/docker-laravel
docker-compose.yml に phpMyAdmin のサービスを追加
docker-compose.ymlvolumes: # 追記 pma-session-store: services: # 追記 pma: image: phpmyadmin/phpmyadmin:5.0.2 environment: - PMA_HOST=db - PMA_USER=root - PMA_PASSWORD=secret ports: - 8080:80 volumes: - pma-session-store:/sessionsDockerコンテナの構築
$ docker-compose up -dphpMyAdmin へアクセス
上記のURLへアクセスし、phpMyAdminの画面が表示されればokです。
補足
MySQL新認証プラグイン caching_sha2_password
私のdbコンテナの設定でMySQL8.0系で認証方式を新しいcaching_sha2_passwordに設定しています。phpMyAdminは5.0.1以降でないとcaching_sha2_passwordに対応していないのでタグで新しいバージョンを明示的に指定してます。latestが5系を指すようになったら外してもいいかもです。
蛇足
(MySQLのCLIやSequel Ace等のクライアントツールで特に不便がないのでがあるので個人的にはphpMyAdminは入れなくてもいいかなと思ってます)
- 投稿日:2020-09-22T19:40:32+09:00
Docker x Laravel phpMyAdmin のコンテナを構築する
以前の記事(最強のLaravel開発環境をDockerを使って構築する【新編集版】)のコメントにてphpMyAdminを使用したいという要望がありましたので補足の記事を作成させていただきます。
手順
https://github.com/ucan-lab/docker-laravel
docker-compose.yml に phpMyAdmin のサービスを追加
docker-compose.ymlvolumes: # 追記 pma-session-store: services: # 追記 pma: image: phpmyadmin/phpmyadmin:5.0.2 environment: - PMA_HOST=db - PMA_USER=root - PMA_PASSWORD=secret ports: - 8080:80 volumes: - pma-session-store:/sessionsDockerコンテナの構築
$ docker-compose up -dphpMyAdmin へアクセス
上記のURLへアクセスし、phpMyAdminの画面が表示されればokです。
補足
MySQL新認証プラグイン caching_sha2_password
私のdbコンテナの設定でMySQL8.0系で認証方式を新しいcaching_sha2_passwordに設定しています。phpMyAdminは5.0.1以降でないとcaching_sha2_passwordに対応していないのでタグで新しいバージョンを明示的に指定してます。latestが5系を指すようになったら外してもいいかもです。
蛇足
(MySQLのCLIやSequel Ace等のクライアントツールで特に不便がないのでがあるので個人的にはphpMyAdminは入れなくてもいいかなと思ってます)
- 投稿日:2020-09-22T17:19:27+09:00
[Rails6]devise + paranoia + MySQL8系で実現するユーザー論理削除と一意制約の両立
はじめに
タイトルの環境にて、ユーザーの論理削除および一意制約の両立にかなり苦戦したので
解決方法を軽くまとめます。
deviseの一意制約をオーバーライドして独自の制約を持たせる方法などが出ていましたが
どれも面倒でもっと簡単にできないかと思い調べた結果です。やりたいこと
先の環境にて(特にMySQL)、deviseデフォルトのユーザー物理削除ではなく論理削除を行い、
かつ退会したユーザーが同じアドレスやIDで再登録できるよう一意制約を担保したい。PostgreSQL, SQLite
こちら2つのDBでは部分indexを活用することで簡単に実装できるそうです。
・実装記事
・add_index仕様1
・add_index仕様2この、部分indexをMySQLは採用しておらず簡単に扱えない模様。
(情報が5.7ばかりだから8系では採用しているのか?どちらにしろRailsのmigrateからは無理そう)
軽くアンチMySQLになるかも…結論(MySQLでの実現方法)
この記事みたらいけると思います。
https://vanhuyz.com/how-to-apply-unique-restriction-with-soft-delete-in-rails/
1. deleted_atカラムを追加後、
2. deleted_atにNullではなくアクティブユーザーにも特定の値をもたせることで、
2カラムでのUNIQUEを実現し(dleted_atがNULLだと実現しない)
3. シンプルに論理削除と一意制約を両立最高に優良な記事をどうもありがとう!!
実装
[環境]
- Ruby:2.6.6p146
- Rails:6.0.3.3
- MySQL:8.0.21
- mysql2:0.5.3
- devise:4.7.2
- paranoia:2.4.2準備
環境構築やdevise, paranoia導入等の基本部分の実装は他に沢山の記事が出ているので割愛します。
devise標準の会員登録・退会機能等が動作する前提です。1. 設定ファイルparanoia.rbを作る
config/initializers/paranoia.rb# ユーザー退会後の論理削除・一意制約を両立させるための処理 # 非削除レコードはdeleted_at = '0000-01-01 00:00:00' # 削除済みレコードはdeleted_at != '0000-01-01 00:00:00' Paranoia.default_sentinel_value = DateTime.new(0)2. migrationでのindex変更
デフォルトのUsersテーブルのindexを変更するマイグレーションファイルを作成
rails g Change_Index_To_Users作成したマイグレーションファイルを以下のように変更
一度デフォルトで作成されたemailインデックスを削除し
新たに[email, deleted_at]でのuniqueインデックスを作成db/migrate/202009220000000.rbclass ChangeIndexUniuqueToUsers < ActiveRecord::Migration[6.0] def change remove_index :users, :email add_index :users, [:email,:deleted_at], unique: true end endmigration
rails db:migrate3. Validation追加
アプリケーションレベルでのバリデーションを追加
app/models/user.rbclass User < ActiveRecord::Base acts_as_paranoid validates :email, uniqueness: { scope: :deleted_at }4. 動作確認
railsコンソールもしくはrailsサーバーを立ち上げ実際にユーザー作成、退会、同アドレスでの再登録を実施してDBを確認します。
無事同じアドレスでの再登録に成功しました!!
他何かいい方法などあれば是非教えてくださいませ~!
- 投稿日:2020-09-22T14:25:02+09:00
Go+MySQL+Dockerで簡単なCRUDを実装する
はじめに
先日、「業務で使う予定ないとはいえGoぐらいある程度知っておいたほうがいいよな...」と思い、Goを使って簡単なCRUDを実装してみたのでそのやり方を備忘録としてまとめておきます。
基本的には以下のサイトの内容を組み合わせて少しアレンジしたものになっています。Goの勉強をする上でこれらのサイトには非常にお世話になったのでこちらもご参考ください。
DockerでGoの開発環境を構築する
Go / Gin で超簡単なWebアプリを作る
Go言語(Golang)入門~MySQL接続編~
docker-compose MySQL8.0 のDBコンテナを作成する
docker-compose upでMySQLが起動するまで待つ方法(2種類紹介)GoをDockerで立ち上げる
まずはGoをDockerで立ち上げていきます。
作業ディレクトリ直下に
- DockerFile
- docker-compose.yml
- main.go
を作成しますDockerFileFROM golang:latest RUN mkdir /app WORKDIR /appdocker-compose.ymlversion: '3' services: go: build: context: . dockerfile: DockerFile command: /bin/sh -c "go run main.go" stdin_open: true tty: true volumes: - .:/appmain.gopackage main import "fmt" func main() { fmt.Println("Hello, World!") }これで
docker-compose up
を行うとコンソール上にHello, World!と出てくると思います。
これが出ればまずGoの起動は成功です。簡単に各ファイルの解説をします。
・DockerFile
Goのコンテナ(仮想環境)を作成します。
ここでWORKDIR /app
を指定していることで以降の動作をすべて/app
以下で行ってくれます。・docker-compose.yml
DockerFileで作ったコンテナを立ち上げるときの設定などを書きます。
これにより、DockerFileにあるコンテナを立ち上げてその中でgo run main.go
のコマンドを叩いてmain.goを起動します・main.go
Goに関する処理はここに書いていきます。今回はHello, World!を出力するだけで終了しています。GoでWebページを作成する
とりあえずGoの起動ができたので次はGoを使ってWebページを作っていきましょう。
今回はGinというフレームワークを使ってみます。
- DockerFileにインストールを追加
- docker-compose.ymlにportsの記述を追加
- main.goの内容を書き換え
- templates/index.htmlを作成
を行ってください。DockerFileFROM golang:latest RUN mkdir /app WORKDIR /app RUN go get github.com/gin-gonic/gindocker-compose.ymlversion: '3' services: go: build: context: . dockerfile: DockerFile command: /bin/sh -c "go run main.go" stdin_open: true tty: true volumes: - .:/app ports: - 8080:8080main.gopackage main import ( "github.com/gin-gonic/gin" ) func main() { router := gin.Default() router.LoadHTMLGlob("templates/*.html") router.GET("/", func(ctx *gin.Context){ ctx.HTML(200, "index.html", gin.H{}) }) router.Run() }templates/index.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Sample App</title> </head> <body> <h1>Hello World!!!</h1> </body> </html>これで
docker-compose build docker-compose up -dを行ってしばらく待ってから
http://localhost:8080にアクセスするとHello World!と表示されると思います。今回やったことを解説します。
今回はGinというフレームワークを追加しました。
GinはDockerFileでコンテナ作成後にgo get github.com/gin-gonic/gin
というコマンドでインストールされ、main.goで呼び出されます。
そしてmain.goの中でtemplatesの中身が読み取られ、router.GET("/", func(ctx *gin.Context){ ctx.HTML(200, "index.html", gin.H{}) })によってroot("/")に対してtemplates/index.htmlが紐づけられることになります。
ちなみにrouter.GETの第一引数("/")を"/test"などに変えると、http://localhost:8080ではなく、http://localhost:8080/testでindex.htmlが表示されるようになります。最後にdocker-compose.ymlにportを追加することでlocalhost:8080へのアクセスを可能にしています。
DockerでMySQLを起動する
ここまででGoでのWebページ作成はできるようになりました。しかし、実際にはWebサービスを作るときにDBとの接続は避けて通れない内容になってきます。
そこで次はDockerを使ってMySQLを立ち上げていきます。まずはdocker-compose.ymlに
・dbコンテナについての記述
・volumeの記述
を追加してください。docker-compose.ymldb: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: go_database MYSQL_USER: go_test MYSQL_PASSWORD: password TZ: 'Asia/Tokyo' command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - db-data:/var/lib/mysql - ./db/my.cnf:/etc/mysql/conf.d/my.cnf ports: - 3306:3306 volumes: db-data: driver: localまた、dbディレクトリを作り、その中にmy.cnfファイルを作成してください。
my.cnf[mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_bin default-time-zone = SYSTEM log_timestamps = SYSTEM default-authentication-plugin = mysql_native_password [mysql] default-character-set = utf8mb4 [client] default-character-set = utf8mb4(この辺は参考ページそのままです。ログに関する部分だけなぜか上手くいかなかったので外しています)
ここまでやって
docker-compose up -d
をやるとMySQLのコンテナも立ち上がるはずです。
設定の記述しかないのでここの説明は省略します。GoとMySQLを接続する
MySQLが立ち上がったので早速Goにつないでみます。
今回は接続にsqlドライバーとGORMというフレームワークを使います。
- DockerFileにインストールの追加
- docker-compose.ymlに依存関係の記述を追加
- main.goにDB接続の処理を追加
を行ってください。DockerFileFROM golang:latest RUN mkdir /app WORKDIR /app RUN go get github.com/gin-gonic/gin RUN go get github.com/go-sql-driver/mysql RUN go get github.com/jinzhu/gormdocker-compose.ymlversion: '3' services: go: build: context: . dockerfile: DockerFile command: /bin/sh -c "go run main.go" stdin_open: true tty: true volumes: - .:/app ports: - 8080:8080 depends_on: - "db" db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: go_database MYSQL_USER: go_test MYSQL_PASSWORD: password TZ: 'Asia/Tokyo' command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - db-data:/var/lib/mysql - ./db/my.cnf:/etc/mysql/conf.d/my.cnf ports: - 3306:3306 volumes: db-data: driver: localmain.gopackage main import ( "fmt" "time" "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" _ "github.com/go-sql-driver/mysql" ) func main() { db := sqlConnect() defer db.Close() router := gin.Default() router.LoadHTMLGlob("templates/*.html") router.GET("/", func(ctx *gin.Context){ ctx.HTML(200, "index.html", gin.H{}) }) router.Run() } func sqlConnect() (database *gorm.DB) { DBMS := "mysql" USER := "go_test" PASS := "password" PROTOCOL := "tcp(db:3306)" DBNAME := "go_database" CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=true&loc=Asia%2FTokyo" count := 0 db, err := gorm.Open(DBMS, CONNECT) if err != nil { for { if err == nil { fmt.Println("") break } fmt.Print(".") time.Sleep(time.Second) count++ if count > 180 { fmt.Println("") fmt.Println("DB接続失敗") panic(err) } db, err = gorm.Open(DBMS, CONNECT) } } fmt.Println("DB接続成功") return db }これで
docker compose up
を行い、コンソールに「DB接続成功」と出たら成功です。追加された内容はsqlConnectがメインなのでそこを解説します。
func sqlConnect() (database *gorm.DB) { DBMS := "mysql" USER := "go_test" PASS := "password" PROTOCOL := "tcp(db:3306)" DBNAME := "go_database" CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=true&loc=Asia%2FTokyo" count := 0 db, err := gorm.Open(DBMS, CONNECT) if err != nil { for { if err == nil { fmt.Println("") break } fmt.Print(".") time.Sleep(time.Second) count++ if count > 180 { fmt.Println("") fmt.Println("DB接続失敗") panic(err) } db, err = gorm.Open(DBMS, CONNECT) } } fmt.Println("DB接続成功") return db }前半部はDBに接続するための情報を定義しています。docker-compose.ymlで設定した内容を入力してください。
その後、db, err := gorm.Open(DBMS, CONNECT)
でDBに接続します。しかし、MySQLの起動時間によってはこのコマンドが実行される時点でMySQLの準備が完了していない場合があります。
そこでこのコードでは2つの対策をしています。1つめはdocker-compose.ymlでの依存関係の設定です。
ここでdepends_onを設定したことにより、dbコンテナが立ち上がってからgoコンテナが立ち上がるようになります。2つめはリトライ処理です。
dbコンテナが起動してからもMySQLが立ち上がるまでに時間がかかるのでもしDBにつながらなかった場合に1秒待ってからリトライするようにしています。
これだと本当にエラーのときにリトライし続けてしまうので適当な回数でエラーを返すようにします。このコードでは3分つながらなかったらエラーになるようになっています。CRUDを実装する
ついにMySQLにもつながるようになったので最後にCRUDの処理を実装して実際の流れをみていきましょう。
あと変更するのはmain.goとindex.htmlのみです。
- Userの定義を作成
- マイグレーション
- post処理の実装
- ユーザー追加フォーム、ユーザー削除ボタンの実装
をやっていきます。main.gopackage main import ( "fmt" "strconv" "time" "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" _ "github.com/go-sql-driver/mysql" ) type User struct { gorm.Model Name string Email string } func main() { db := sqlConnect() db.AutoMigrate(&User{}) defer db.Close() router := gin.Default() router.LoadHTMLGlob("templates/*.html") router.GET("/", func(ctx *gin.Context){ db := sqlConnect() var users []User db.Order("created_at asc").Find(&users) defer db.Close() ctx.HTML(200, "index.html", gin.H{ "users": users, }) }) router.POST("/new", func(ctx *gin.Context) { db := sqlConnect() name := ctx.PostForm("name") email := ctx.PostForm("email") fmt.Println("create user " + name + " with email " + email) db.Create(&User{Name: name, Email: email}) defer db.Close() ctx.Redirect(302, "/") }) router.POST("/delete/:id", func(ctx *gin.Context) { db := sqlConnect() n := ctx.Param("id") id, err := strconv.Atoi(n) if err != nil { panic("id is not a number") } var user User db.First(&user, id) db.Delete(&user) defer db.Close() ctx.Redirect(302, "/") }) router.Run() } func sqlConnect() (database *gorm.DB) { DBMS := "mysql" USER := "go_test" PASS := "password" PROTOCOL := "tcp(db:3306)" DBNAME := "go_database" CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=true&loc=Asia%2FTokyo" count := 0 db, err := gorm.Open(DBMS, CONNECT) if err != nil { for { if err == nil { fmt.Println("") break } fmt.Print(".") time.Sleep(time.Second) count++ if count > 180 { fmt.Println("") panic(err) } db, err = gorm.Open(DBMS, CONNECT) } } return db }templates/index.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Sample App</title> </head> <body> <h2>ユーザー追加</h2> <form method="post" action="/new"> <p>名前<input type="text" name="name" size="30" placeholder="入力してください" ></p> <p>メールアドレス<input type="text" name="email" size="30" placeholder="入力してください" ></p> <p><input type="submit" value="Send"></p> </form> <h2>ユーザー一覧</h2> <table> <tr> <td>名前</td> <td>メールアドレス</td> </tr> {{ range .users }} <tr> <td>{{ .Name }}</td> <td>{{ .Email }}</td> <td> <form method="post" action="/delete/{{.ID}}"> <button type="submit">削除</button> </form> </td> </tr> {{ end }} </ul> </body> </html>これで
docker-compose up -d
を行い、http://localhost:8080にアクセスするとユーザー登録フォームが現れ、ユーザーを登録すると下に登録したユーザーの情報が表示されるようになります。
また、コンテナを削除して上げ直しても登録されたユーザーは削除されず、ユーザー一覧に表示が残るようになります。それでは追加部分の解説をしていきます。
まず、main.goでUserという構造体を作成しています。gorm.Model
でidなどモデルに必要な内容をUserに入れ、更にUser特有のname, emailを追加しています。
この構造はdb.AutoMigrate
によってDBに反映されます。続いて各パスでのCRUD処理を実装していきます。
rootパスではユーザー一覧を取得します。
db.Find(&users)でDB内にあるユーザー一覧をUser構造として取得します。
間にOrderを挟むことで取得時に古いユーザーが上に来るようにしています。
最後に取得したユーザーをindex.htmlに渡しています。/newパスではフォームの内容をもとにユーザーを作成しています。
ctx.PostFormでフォームによってsubmitされた内容を取得し、その内容をdb.Createで永続化しています。
処理が終わったらrootにリダイレクトします。/deleteパスではidを指定してユーザーを削除しています。
こちらではURLにユーザーのidを指定しているのですが、同様にctxから取得します。
そしてその内容からdb.Firstでユーザーを取得し、db.Deleteで該当のユーザーを削除します。
ここで、idはstringで渡されているのでstrconv.Atoiでint型に変換していることに注意してください。index.htmlでは一般的なhtmlの書き方でformとtableを作成しています。
ここで、{{ range .users }}
という形でmain.goから渡されたusersを受け取っています。おわりに
今回はGoでのWebサービス開発の導入としてGo+MySQL+Dockerで簡単なCRUDを実装してみました。あくまで練習なのでバリデーションとか細かい制御などは考えていません。
今回行った内容は初歩ではありますが、この内容を広げて複雑化していくことで実際にWebサービスを作ることができると思います。
もしGoで何か作ってみたいと考えている方がいらっしゃったらぜひ参考にしてみてください!
- 投稿日:2020-09-22T14:03:44+09:00
libmysqlclient.so.18がないといわれる
対応
インストール
yum update -y yum install -y gcc mysql-devel mysql-libs # ↓どっちかに入る # /lib64/mysql/libmysqlclient.so.18 # /usr/lib64/mysql/libmysqlclient.so.18それでも動かない場合
環境変数、
LD_LIBRARY_PATH
が通っている場所へlibmysqlclient.so.18
をコピーする。※
実体はlibmysqlclient.so.18.0.0
になっているので注意
(libmysqlclient.so.18
はシンボリックリンク)特にLambda上で必要な場合などは注意。
# Lambda上 LD_LIBRARY_PATH=/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib
- 投稿日:2020-09-22T09:29:19+09:00
【初心者向け】データベースのテーブル設計で僕が意識している6つのこと
はじめまして、himakuroです。
2017年ぐらいからQiitaに記事を投下しようと考えていたのですが、なかなか筆が乗らずようやく初投稿です
軽く自己紹介をしておくと、普段は社内SEとしてPHP、Ruby、Golangを書いたり、
趣味の個人ブログ方ではプログラミング初心者に向けた記事や雑記的なものを書いたりしています。今回は記念すべき1つ目の記事と言う事で
僕が普段テーブル設計(主に命名)で気をつけている6つの事を書きました。僕の好みも含まれていますが、初心者の方がテーブルやカラム名を決める際の参考になればなと思います。
テーブル名は必ず複数形にする
テーブルは一つしかないから単数形を使うべき!
Modelも単数形で定義するじゃん!みたいな反論が聞こえてきそうですが、僕は複数形で定義する派です。
また複数形にする場合に、テーブル名の途中の部分を複数形にしている物をたまに見かけますが、僕は末尾を複数形で統一するのが好きです。
x
user_bank
xusers_bank
ouser_banks
Railsで開発をしている方は、僕と同じ様に末尾が複数形の方が好きという人が多い(はず?)
カラム名のsuffixとして_idを無闇に使わない
suffix(サフィックス)とは
user_id
やpost_id
で言う_id
の部分を指しています。
要は末尾に付ける物ですね。そしてこの
_id
は、他テーブルの主キーを指すのに利用して行きたいので
categoriesテーブルが存在しないのに、category_id
をpostsテーブルに追加するなんて事はしません。また命名規則としては
テーブル名(単数形)_id
で統一するのがおすすめです。x
categories_id
xid_category
ocategory_id
同じものを指すカラムは型を統一する
※ コメントでご指摘を頂いたため2020-09-24に内容を更新しました
1つ前の内容に少し関連しているのですが
他テーブルのauto incrementなid列と関連付けるための
テーブル名(単数形)_id
カラムを定義する際には型はunsignedのbigintで統一しています。理由としてはRailsやLaravelなどでauto incrementのid列を定義すると,
id
はunsigned bigintになるからです。本来ならカラムの型はどのようなデータが入るかを意識した上で選定するべきですが
フレームワークを使っていると自動で型が確定するものがあり、今回の内容がそれに該当します。自動で型が確定するカラムは実際にどのような型になっているかを確認するのを疎かにしがちで、
今まで携わったLaravelやRailsのプロジェクトでも、 auto incrementな他テーブルのidを参照するxxx_id
をbigintではなくintで定義しているのを多数見てきました。
xxx_id
に限らず同じ意味を持つカラムは同じ型で定義するように意識していきましょう。履歴テーブルはhistory、ログテーブルはlog
履歴テーブルとログテーブルって何が違うの?
と聞かれたら僕は
履歴テーブルは画面に表示して ユーザー(利用者)に見せるもの
ログテーブルは エンジニア(開発者)などが調査に使用するものと答えます。
また命名に関しては、例えばゲーム開発などでユーザーがゲーム画面で閲覧する事が出来るプレゼント履歴用のテーブルを作る場合は
user_present_histories
と名付けます。ユーザーからアイテム消えたんだけど?みたいなお問い合わせが来た場合に、エンジニアが調査が出来るようにユーザーのアイテム利用ログを残しておく場合は
user_item_logs
と名付けます。人によっては
history
やlog
をprefix(プレフィックス)として先頭に持って来る方もいると思いますが、この辺りは好みかなと思います。o
user_item_logs
olog_user_items
booleanのカラムはひと目で分かるようにする
型がbooleanのカラムはひと目でわかるように
is_
can_
has_
の様なprefixを付けるようにしています。例:
is_active
,has_owner
こうすることで、これらのカラム名を見ただけで
型がbooleanであることが推測でき、更にtrueやfalseなどの値が入っていた時に
何を意味するのかが明確になります。ちなみに型がbooleanで
check_xxx
の様なカラムをたまに見かけますが
これではtrue
の場合にはチェックが必要なのか、それともチェックが終わっているのかが明確ではないので、booleanのカラム名としてcheck
はおすすめしません。日付を保持するカラムの命名方法
日付を保持するカラムを命名する際に
finish_at
にするかfinished_at
にするかで迷ったことはありませんか?これを迷わなくするためには カラムで保持するデータが未来を指すのか、過去のものを指すのか を考慮すると良いです。
過去形を使わない例
例えばゲーム開発でイベント情報を持つテーブルがあり、そのテーブルにはイベント開始時刻と、終了時刻を持つカラムがあるとします。
イベントの開催情報は事前告知するのが一般的であり、イベント開始時刻と終了時刻には未来の時間を保持することになります。
よって、カラム名も過去形にはせずに
start_at
やfinish_at
の様に命名をしていきます。過去形を使う例
続いて過去形で命名をする場合を見ていきます。
user_quests
と言うユーザーのクエスト情報を管理するテーブルがあり、そこにはユーザーがクエストを開始した時刻と終了した時刻を保持するカラムがあるとします。これらのカラムにデータが入るのはユーザーがクエストを開始した時、終了した時なので、データとしては過去の時間を指していることになります。
よってカラム名は
started_at
finished_at
のように過去形で命名をします。レコードの作成時間や更新時間を保持するカラムとして
created_at
やupdated_at
などがあると思いますが、これらのカラムのデータも作成された時間、更新された時間を保持するので過去形ですね。テーブルの設計って大変
一般的にテーブル設計って聞くと、正規化とかパフォーマンスを意識したインデックスの貼り方とか難しい事ばかりを意識しがちですが、それ以前にテーブル名やカラム名を意識するのも大切だよというのを伝えたかったのでこの記事を書きました。
これが正解と言うわけではありませんが、テーブル名やカラム名はとても重要なので
ネーミングセンスが無いから適当につけよ…とは思わずに、しっかりと考えて命名をするようにしましょう。初投稿 完
- 投稿日:2020-09-22T08:07:22+09:00
PythonでMySQLに接続する方法【初心者向け】
◎下記を参照してDBへのコネクト、SELECT分をためしてみる。
パッケージはmysqlclientを利用する
PythonでMySQLに接続する方法【初心者向け】PythonでMySQLに接続する書き方は、そのままではエラーとなるので、下記を利用すること。
#mysqlclientパッケージを利用する import MySQLdb # 接続する conn = MySQLdb.connect( user='root', passwd='root', host='localhost', db='mstibqym_crontest') # カーソルを取得する cur = conn.cursor() # SQL(データベースを操作するコマンド)を実行する sql = "select * from test_table" cur.execute(sql) # 実行結果を取得する rows = cur.fetchall() # 一行ずつ表示する for row in rows: print(row) cur.close # 接続を閉じる conn.close◎INSERT分参考
Python3でMySQLを使う – 基本操作からエラー処理までサンプルコード付
- 投稿日:2020-09-22T08:07:22+09:00
PythonでMySQLにINSERTする【初心者向け】
◎下記を参照してDBへのコネクト、SELECT分をためしてみる。
パッケージはmysqlclientを利用する
PythonでMySQLに接続する方法【初心者向け】PythonでMySQLに接続する書き方は、そのままではエラーとなるので、下記を利用すること。
#mysqlclientパッケージを利用する import MySQLdb # 接続する conn = MySQLdb.connect( user='root', passwd='root', host='localhost', db='mstibqym_crontest') # カーソルを取得する cur = conn.cursor() # SQL(データベースを操作するコマンド)を実行する sql = "select * from test_table" cur.execute(sql) # 実行結果を取得する rows = cur.fetchall() # 一行ずつ表示する for row in rows: print(row) cur.close # 接続を閉じる conn.close◎INSERT分は下記を参考に実施
Python3でMySQLを使う – 基本操作からエラー処理までサンプルコード付#mysqlclientパッケージを利用する import MySQLdb # 接続する conn = MySQLdb.connect( user='root', passwd='root', host='localhost', db='mstibqym_crontest') # カーソルを取得する cur = conn.cursor() # SQL(データベースを操作するコマンド)を実行する sql = "INSERT INTO test_table (item) VALUES('xyzss')" cur.execute(sql) conn.commit() cur.close # 接続を閉じる conn.close