0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails6.1】本番環境で発生したMysqlのサブクエリに関するエラーを解消

Last updated at Posted at 2024-06-21

はじめに

デプロイを行った際にSQLでエラーが発生しました。

ActionView::Template::Error (Mysql2::Error: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'):

エラーの内容

Google翻訳より…
このバージョンの MySQL はまだ「LIMIT & IN/ALL/ANY/SOME サブクエリ」をサポートしていません

LIMIT句が使用されている箇所の構文が、MySQLのバージョンで使用できない記述になっているようです。

さらにエラーメッセージを見ると、以下のビューを表示する際に引っかかっているようでした。

ショップ(Shop)詳細(show)のビューページ
<%= image_tag @shop.get_shop_image(500,500), class: "w-100 p-1" %>
<%= render 'public/favorite_shops/btn', shop: @shop %>
<%= link_to review_path(@shop), class: "btn btn-outline-info d-grid mt-2" do %>
   ショップの口コミを見る (<%= @reviews.count %>)
<% end %>
<% if current_shop == @shop %>
  <% unless current_shop.guest_shop? %>

そもそもサブクエリって何だろう…?ということで検索…

サブクエリ(副問い合わせ)とは、クエリの中で使用される別のクエリのことを指します。サブクエリを使用すると、複雑な条件を持つクエリを簡潔に表現でき、データの抽出や加工をより柔軟に行うことができます。

つまり、今回のエラーはINかALLかANYかSOMEのサブクエリが生成されているということ…?

コントローラの確認

先ほどのビューを表示するためのアクション(show)を確認してみます。

コントローラ
class Public::ShopsController < ApplicationController
  def show
    @member = current_member
    @shop = Shop.find(params[:id])
    @items = @shop.items.order(id: "DESC").page(params[:page])
    
    # ↓怪しいのはこれ
    shop_pre_orders = PreOrder.where(item_id: @items)
    @reviews = Review.where(pre_order_id: shop_pre_orders)
                     .where(is_active: 'true')
                     
    @tag_rank = Tag.tag_rank_item
  end
end

shop_pre_orders = PreOrder.where(item_id: @​items)を見ると、ここで必要なのは@​itemsのidのみなのに、@​items全てから参照しようとしてしまっています。

これによって、クエリの中にサブクエリが生成されてしまっているのでしょうか…?

確かにSQLの内容を見てもIN(...IN (...))みたいに書かれていたような…
この中のIN(...)がサブクエリということ…?

先ほどのエラーメッセージにも「LIMIT & IN/ALL/ANY/SOME サブクエリ」をサポートしていませんとあったので、INになっている部分が怪しいような気もしてきました。

これを修正していきます。

コントローラ
class Public::ShopsController < ApplicationController
  def show
    @member = current_member
    @shop = Shop.find(params[:id])
    @items = @shop.items.order(id: "DESC").page(params[:page])
    
-   shop_pre_orders = PreOrder.where(item_id: @items)
-   @reviews = Review.where(pre_order_id: shop_pre_orders)
+   shop_pre_order_ids = PreOrder.where(item_id: @items.pluck(:id)).pluck(:id)
+   @reviews = Review.where(pre_order_id: shop_pre_order_ids)
                     .where(is_active: 'true')
                     
    @tag_rank = Tag.tag_rank_item
  end
end

pluckでidのみを呼び出しています。
これでビューを表示してみるとSQL文もさっきの形と変わっていました。
(SQL文を記録していなかったので曖昧な表現になっています。)

これを本番環境で実行してみると…エラーが表示されなくなりました!

おわりに

ツールの違いによって開発環境ではエラーは出ないけど、デプロイ時にエラーが出るということもあるんだなと勉強になりました。

SQLのことも全然分からないまま学習を進めていたので、きちんと調べてみようと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?