- 投稿日:2020-11-22T15:21:42+09:00
Laravel:SQLSTATE[42000]: Syntax error or access violation...bytesの解決
【概要】
1.結論
5.参考URL
6.開発環境
1.結論
app/Providers/AppServiceProvider
のpublic function boot()
にSchema::defaultStringLength(191);
を記載する!2.SQLSTATE[42000]とは何か
アクセス違反ですという意味で、SQL文の文法に誤りがあるということです。ただ、それに起因してデータがパンパンになっているためこのエラーになっています。
3.なぜこのエラーになったのか
結論から言いますとLaravelとMysqlのバージョンのせいで、Mysqlのカラムや中身の文字列がデータ量(767bytesがMAX)を超えたからでした。UTF8MB4になり1文字あたりのデータ量(4bytes)が増えたからのようです。
(大変参考になったURLを下記(参考URL)に添付しています。)4.どのように解決したのか
app/Providers/AppServiceProvideruse Illuminate\Support\Facades\Schema; //⬅︎を追加記載(❶) use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { // 省略 public function boot() { Schema::defaultStringLength(191); //⬅︎を追加記載(❷) } }4bytes*191文字=764bytesに抑えることで、規定量以下にしました。これをデフォルト設定にしているのでどのテーブルにもこれが適用されます。Mysqlのバージョンアップもありましたが、手軽かつアプリを使用する際に100文字を超える実装はなかったので今回はこの手段を取りました。また❶を記載しないとエラーが起きます。
5.参考URL
①Laravel5.4以上、MySQL5.7.7未満 でusersテーブルのマイグレーションを実行すると Syntax error が発生する
②【Laravel】migrateでテーブルが存在したらスキップする6.開発環境
PHP 7.4.10
Laravel 8.9.0
MySQL 5.6.47/SequelPro 1.1.2
- 投稿日:2020-11-22T15:21:42+09:00
Laravel:SQLSTATE[42000]Syntax error or access violation...bytesの解決
【概要】
1.結論
5.参考URL
6.開発環境
1.結論
app/Providers/AppServiceProvider
のpublic function boot()
にSchema::defaultStringLength(191);
を記載する!2.SQLSTATE[42000]とは何か
アクセス違反ですという意味で、SQL文の文法に誤りがあるということです。ただ、それに起因してデータがパンパンになっているためこのエラーになっています。
3.なぜこのエラーになったのか
結論から言いますとLaravelとMysqlのバージョンのせいで、Mysqlのカラムや中身の文字列がデータ量(767bytesがMAX)を超えたからでした。UTF8MB4になり1文字あたりのデータ量(4bytes)が増えたからのようです。
(大変参考になったURLを下記(参考URL)に添付しています。)4.どのように解決したのか
app/Providers/AppServiceProvideruse Illuminate\Support\Facades\Schema; //⬅︎を追加記載(❶) use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { // 省略 public function boot() { Schema::defaultStringLength(191); //⬅︎を追加記載(❷) } }4bytes*191文字=764bytesに抑えることで、規定量以下にしました。これをデフォルト設定にしているのでどのテーブルにもこれが適用されます。Mysqlのバージョンアップもありましたが、手軽かつアプリを使用する際に100文字を超える実装はなかったので今回はこの手段を取りました。また❶を記載しないとエラーが起きます。
5.参考URL
①Laravel5.4以上、MySQL5.7.7未満 でusersテーブルのマイグレーションを実行すると Syntax error が発生する
②【Laravel】migrateでテーブルが存在したらスキップする6.開発環境
PHP 7.4.10
Laravel 8.9.0
MySQL 5.6.47/SequelPro 1.1.2
- 投稿日:2020-11-22T15:03:58+09:00
【Rails6】Railsの既存アプリをDockerizeする【Docker】
はじめに
Hello,Qiita!
今回は既存のRailsアプリをDockerに乗せてみようと思います!
コンテナの中に環境を移すというシンプルなものですが、
webpackやyarnのインストールで少し引っ掛かったので、記事にしてみました!
docker-composeでRailsとMySQLの2つのコンテナをオーケストレーションしてみましょう
それではいきましょう!!前提条件
- OS: MacOS
- Ruby: 2.7.1
- Rails: 6.0.3
- データベース: MySQL
- Docker: 19.03.13
Dockerfileの記述
以下のように記述します。
DockerfileFROM ruby:2.7.1 ENV BUNDLER_VERSION="2.1.4" \ APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn \ TZ=Asia/Tokyo RUN apt-get update && apt-get install -y \ build-essential \ libpq-dev \ nodejs \ mariadb-client \ sudo \ vim && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn WORKDIR /app COPY Gemfile Gemfile.lock /app/ COPY . /app RUN bundle install -j4 && \ yarn upgrade && \ rails webpacker:install && \ yarn install --check-files COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 CMD ["rails", "server", "-b", "0.0.0.0"]何をやっているのか
FROM
Docker Hub にある(今回はRubyのバージョン2.7.1の)公式イメージを取ってくる。
ENV
環境変数の定義をする。
APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
↑これを書くとWarningメッセージを非表示にできるRUN
Dockerコンテナ上でコマンドを実行する。
apt-get
このコマンドは、Debian系ディストリビューション(DebianやUbuntu)のパッケージ管理システムであるAPT(Advanced Package Tool)ライブラリを利用してパッケージを操作・管理する、という意味。今回はRubyのイメージを取ってきたが、Debianイメージの上にrubyがインストールされてある。DebianはLinuxカーネルを利用しているためLinuxコマンドが使える。WORKDIR
ワークディレクトリの設定をする。
同じDockerfile内に複数回指定可能で、ENVで登録したパスを利用してもよい。COPY
新しいファイルをフォルダコピーする(圧縮されているファイルは展開されない)。
ENTRYPOINT
記述されたコマンドの実行をする。
EXPOSE
特定のポートを解放する。
CMD
実行するコンテナのデフォルト値を設定する。
同じDockerfile内で使用できるのは一回のみで、ENTRYPOINTに対して引数を設定することも可能である。
Dockerfileには、少なくとも一回はENTRYPOINTかCMDを記載すべき。docker-compose.ymlの記述
以下のように記述します。
docker-compose.ymlversion: '3' services: app: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp - ./vendor/bundle:/myapp/vendor/bundle:delegated ports: - "19802:3000" # "任意のポート:3000" とする depends_on: - db tty: true stdin_open: true db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: "password" ports: - "19801:3306" # こちらも、"任意のポート:3306"とする volumes: - ./tmp/db:/var/lib/mysql何をやっているのか
version
使用するdocker-composeのバージョンを定義する。
services
アプリケーションを動かすための各要素(service)を定義する。(今回は
app
とdb
)build
composeファイルを実行し、ビルドされるときのパスを指定する。
command
デフォルトコマンドをオーバーライドする。
volumes
マウントする設定ファイルのパスを指定する。
ports
Dockerイメージを立ち上げる際のポート番号を指定する。
depends_on
service同士の依存関係を指定する。
environment
環境変数を指定する。
tty: true
コンテナが起動し続けるよう設定する。
stdin_open: true
コンテナ内の標準入出力の許可を設定する。
entrypoint.shの記述
以下のように記述します。
entrypoint.sh#!/bin/bash set -e # Railsのserver.pidファイルを取り除く rm -f /app/tmp/pids/server.pid # コンテナのメインプロセスを実行する (DockerfileでCMDと設定されているもの)。 exec "$@"database.ymlの記述
以下のように記述します。
database.ymldefault: &default adapter: mysql2 pool: 5 timeout: 5000 # 任意 development: <<: *default database: myapp_development username: root password: password host: db port: 3306GemfileとGemfile.lockの確認
今回は既存アプリをDockerにのせるので、GemfileとGemfile.lockが存在していることを確認するだけで良いです。
docker-composeの起動
ターミナルで
docker-compose build
を実行します。ターミナルSuccessfully built ~ Successfully tagged ~と出力されればビルド成功です。
次に、
docker-compose exec app bash
を実行し、appコンテナ内に入ります。その後、
bundle exec rails db:create
bundle exec rails db:migrate
bundle exec rails db:seed
を実行し、無事完了です!終わりに
最後までご覧いただきありがとうございました。
個人的には、コンテナの中に入って作業をするのがめちゃ楽しいです。
なぜかはわかりません。(インセプション的な気持ちになる)
また、不適切な表現などありましたらお知らせいただけると幸いです。それではまた!
- 投稿日:2020-11-22T03:46:21+09:00
SQL初心者〜中級者のための練習問題&解答例2
第2弾を作ってみました。
SQL力向上のためにお役立てください。その1: SQL初心者〜中級者のための練習問題&解答例1
その3: SQL初心者〜中級者のための練習問題&解答例3題材
社員テーブル
社員番号 氏名 所属部署 趣味1 趣味2 趣味3 1 杉山 圭佑 営業部 サッカー ドライブ 映画鑑賞 2 佐藤 結菜 人事部 映画鑑賞 旅行 インスタ 3 高橋 絵里 経理部 ゲーム NULL NULL 4 早川 良太 人事部 ドライブ 料理 NULL 5 佐藤 一弥 経理部 NULL NULL NULL 6 佐藤 優穂 営業部 インスタ TikTok NULL ※ありがちなDB設計の例として趣味1~3を列で持っていますが、これはSQLアンチパターンの「マルチカラムアトリビュート」に該当するため、設計の参考にはしないでください。アンチパターンのDB設計であっても望むデータを取り出す練習のために、わざとこうしています。
Schema SQL
CREATE TABLE `employees` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` varchar(255) NOT NULL, `department` varchar(255) NOT NULL, `hobby1` varchar(255), `hobby2` varchar(255), `hobby3` varchar(255) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT INTO `employees` (`id`, `name`, `department`, `hobby1`, `hobby2`, `hobby3`) VALUES (1, '杉山 圭佑', '営業部', 'サッカー', 'ドライブ', '映画鑑賞'), (2, '佐藤 結菜', '人事部', '映画鑑賞', '旅行', 'インスタ'), (3, '高橋 絵里', '経理部', 'ゲーム', NULL, NULL), (4, '早川 良太', '人事部', 'ドライブ', '料理', NULL), (5, '佐藤 一弥', '経理部', NULL, NULL, NULL), (6, '佐藤 優穂', '営業部', 'インスタ', 'TikTok', NULL);問1
趣味に映画鑑賞が含まれる社員の名前を一覧で表示せよ。
name 杉山 圭佑 佐藤 結菜
解答例1
SELECT name FROM employees WHERE hobby1 = '映画鑑賞' OR hobby2 = '映画鑑賞' OR hobby3 = '映画鑑賞'
解答例2(提供: @takahasinaoki さん)
SELECT name FROM employees WHERE '映画鑑賞' IN (hobby1, hobby2, hobby3)問2
趣味1~3を縦に表示せよ。
name hobby 杉山 圭佑 サッカー 佐藤 結菜 映画鑑賞 高橋 絵里 ゲーム 早川 良太 ドライブ 佐藤 一弥 NULL 佐藤 優穂 インスタ 杉山 圭佑 ドライブ 佐藤 結菜 旅行 高橋 絵里 NULL 早川 良太 料理 佐藤 一弥 NULL 佐藤 優穂 TikTok 杉山 圭佑 映画鑑賞 佐藤 結菜 インスタ 高橋 絵里 NULL 早川 良太 NULL 佐藤 一弥 NULL 佐藤 優穂 NULL
解答例
SELECT name, hobby1 AS hobby FROM employees UNION ALL SELECT name, hobby2 FROM employees UNION ALL SELECT name, hobby3 FROM employees問3
名字が佐藤である社員の、趣味の数を表示せよ。
name hobby_count 佐藤 一弥 0 佐藤 優穂 2 佐藤 結菜 3
解答例1
SELECT name, COUNT(hobby1) + COUNT(hobby2) + COUNT(hobby3) AS hobby_count FROM employees WHERE name LIKE '佐藤 %' GROUP BY name
解答例2
SELECT name, SUM(CASE WHEN hobby1 IS NOT NULL THEN 1 ELSE 0 END) + SUM(CASE WHEN hobby2 IS NOT NULL THEN 1 ELSE 0 END) + SUM(CASE WHEN hobby3 IS NOT NULL THEN 1 ELSE 0 END) AS hobby_count FROM employees WHERE name LIKE '佐藤 %' GROUP BY name問4
同じ趣味を持つ社員の一覧を表示せよ。
なお、氏名リストの並び順は社員番号の昇順で、区切り文字は「, 」とする。
hobby name_list インスタ 佐藤 結菜, 佐藤 優穂 ドライブ 杉山 圭佑, 早川 良太 映画鑑賞 杉山 圭佑, 佐藤 結菜
解答例
SELECT hobby, GROUP_CONCAT(name ORDER BY id separator ', ') AS name_list FROM ( SELECT id, name, hobby1 AS hobby FROM employees UNION ALL SELECT id, name, hobby2 FROM employees UNION ALL SELECT id, name, hobby3 FROM employees ) hobby_table WHERE hobby IS NOT NULL GROUP BY hobby HAVING COUNT(*) > 1