20201122のMySQLに関する記事は4件です。

Laravel:SQLSTATE[42000]: Syntax error or access violation...bytesの解決

【概要】

1.結論

2.SQLSTATE[42000]とは何か

3.なぜこのエラーになったのか

4.どのように解決したのか

5.参考URL

6.開発環境

1.結論

app/Providers/AppServiceProviderpublic function boot()Schema::defaultStringLength(191);を記載する!

2.SQLSTATE[42000]とは何か

アクセス違反ですという意味で、SQL文の文法に誤りがあるということです。ただ、それに起因してデータがパンパンになっているためこのエラーになっています。

3.なぜこのエラーになったのか

結論から言いますとLaravelとMysqlのバージョンのせいで、Mysqlのカラムや中身の文字列がデータ量(767bytesがMAX)を超えたからでした。UTF8MB4になり1文字あたりのデータ量(4bytes)が増えたからのようです。
(大変参考になったURLを下記(参考URL)に添付しています。)

4.どのように解決したのか

app/Providers/AppServiceProvider
use 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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel:SQLSTATE[42000]Syntax error or access violation...bytesの解決

【概要】

1.結論

2.SQLSTATE[42000]とは何か

3.なぜこのエラーになったのか

4.どのように解決したのか

5.参考URL

6.開発環境

1.結論

app/Providers/AppServiceProviderpublic function boot()Schema::defaultStringLength(191);を記載する!

2.SQLSTATE[42000]とは何か

アクセス違反ですという意味で、SQL文の文法に誤りがあるということです。ただ、それに起因してデータがパンパンになっているためこのエラーになっています。

3.なぜこのエラーになったのか

結論から言いますとLaravelとMysqlのバージョンのせいで、Mysqlのカラムや中身の文字列がデータ量(767bytesがMAX)を超えたからでした。UTF8MB4になり1文字あたりのデータ量(4bytes)が増えたからのようです。
(大変参考になったURLを下記(参考URL)に添付しています。)

4.どのように解決したのか

app/Providers/AppServiceProvider
use 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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6】Railsの既存アプリをDockerizeする【Docker】

はじめに

Hello,Qiita! :sunny:
今回は既存のRailsアプリをDockerに乗せてみようと思います!
コンテナの中に環境を移すというシンプルなものですが、
webpackやyarnのインストールで少し引っ掛かったので、記事にしてみました!
docker-composeでRailsとMySQLの2つのコンテナをオーケストレーションしてみましょう:musical_score:
それではいきましょう!!:whale2:

前提条件

  • OS: MacOS
  • Ruby: 2.7.1
  • Rails: 6.0.3
  • データベース: MySQL
  • Docker: 19.03.13

Dockerfileの記述

以下のように記述します。

Dockerfile
FROM 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.yml
version: '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)を定義する。(今回はappdb)

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.yml
default: &default
  adapter: mysql2
  pool: 5
  timeout: 5000 # 任意

development:
  <<: *default
  database: myapp_development
  username: root
  password: password
  host: db
  port: 3306

Gemfileと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
を実行し、無事完了です!:sunglasses:

終わりに

最後までご覧いただきありがとうございました。
個人的には、コンテナの中に入って作業をするのがめちゃ楽しいです。
なぜかはわかりません。(インセプション的な気持ちになる)
また、不適切な表現などありましたらお知らせいただけると幸いです。

それではまた!:rocket:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む