SQL これは sql_mode=only_full_group_by と互換性がありません

1. バグ記録

1.1. バグのスクリーンショット 

1.2.SQL文 

SELECT id,batch_no,if_code,channel_mch_no,bill_date,bill_type,currency,order_id,
channel_order_no,channel_amount,channel_fee_amount,channel_success_at,
channel_user,channel_state,org_pay_order_id,channel_refund_amount,created_at,
updated_at 
FROM t_check_channel_bill 
WHERE batch_no = 'zjpay_M1638950514_20230410' AND order_id IS NOT NULL 
GROUP BY order_id 
HAVING MAX(channel_success_at)

1.3. 完全なエラー 

Expression #1 of SELECT list is not in GROUP BY clause and contains 
nonaggregated column 'xyzpay.t_check_channel_bill.id' which is not 
functionally dependent on columns in GROUP BY clause; this is 
incompatible with sql_mode=only_full_group_by

2. シナリオの再発 

 3. バグ対応

        上記では、他のデータベースで記述された SQL ステートメントを模倣しましたが、エラーの例はありませんでした。この場合、まずエラーの原因を分析できます。

        1) SQL文エラー

        2) データエラー

        3) 図書館の問題

3.1.SQLエラー解析とデータエラー

        原文:SELECT リストの式 #1 は GROUP BY 句になく、GROUP BY 句の列に機能的に依存していない非集計列 'xyzpay.t_check_channel_bill.id' を含んでいます。これは sql_mode=only_full_group_by と互換性がありません

つまり、select によって選択された列は group by の背後になく、group by 列の機能に依存しません。これは、sql_mode=only_full_group_by とは互換性がありません。エラークエリが原因です。ステートメントに group by 句がある場合、select の後に group by の後の属性、または集計関数 (group by の後ろにない属性) [avg()、max()、分()...]

        しかし、明らかに、私の order_id がクエリ ステートメントに含まれていることがわかります。そのため、このエラーの説明は明らかに不正確です。

        SQL がどのように調整されても、このエラーは常に発生します。エラーの最後の文:これは sqlmode=onlyfull_groupby と互換性がありません。sqlmode を確認しましょう

3.2. ライブラリエラーの分析 

        最初に間違ったライブラリを使用してクエリを実行する

sql语句:
    
    select @@sql_mode

查询结果:

    ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

        次に、「エラー再現」が失敗したことをライブラリに問い合わせます。

sql语句:
    
    select @@sql_mode

查询结果:

    STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

         検出結果が同じではないことがわかるため、ライブラリを変更してこのエラーを再現できるかどうかを確認できます。

        update ステートメントを使用してデータベース自体を変更することはできませんが、セットは直接使用できることに注意してください。

        set はデータベースを変更します。 

SET @@sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,
NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

結果を変更する        

         エラーを再シミュレートすると、エラーが再現され、見つけた場所が正しいことがわかります。

         その後、正常に動作していた SQL に問題があることが判明しました。その後、この SQL エラーがデータベースの原因であると判断できます。これはデータベースに問題があるため、データベースを変更し、このフィールドを変更すれば問題はありません。

SET @@sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

 

これは一時的な変更であり、SQL が再起動されると無効になる        ため、この変更方法には欠陥がありますただ、会社のデータベースを使っているので、データベースは基本的に再起動されないので、そういった問題はありません。ただし、ローカルでテストを実行すると、再起動後にテストが失敗します。

3.3. 永続的な変更

        

my.ini (Windows の MySQL 構成ファイル)
を変更して追加します。

sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION1'


        (ONLY_FULL_GROUP_BYをオフにするのが目的です。表示の便宜上、改行で2行に分けています。実際の足し算では必要ありません。) 修正の際は英語の一重引用符の使用に注意してください
        。 '' を使用してデータをラップします。中国語は使用できません。次に、ファイルを ANSI エンコード形式で保存します。

        注: my.ini は静的ファイルであり、サービスが実行されているかどうかとは関係ありません。したがって、最初にサービスを停止してから my.ini を変更する必要はありません。

4. 拡張

        以下は、MySQL 5.7 公式リファレンスマニュアルの ONLY_FULL_GROUP_BY の説明です。SQL の使用法に関するドキュメント

  

        翻訳は次のとおりです。

        選択リスト、HAVING 条件、または ORDER BY リストが、GROUP BY 句で名前が指定されておらず、GROUP BY 列の機能 (GROUP BY 列によって一意に識別される) にも依存していない非集計列を参照するクエリを拒否します。
        MySQL5.7.5 以降、デフォルトの SQL モードには ONLY_FULL_GROUP_BY が含まれます。(5.7.5 より前では、MySQL は関数の依存関係を検出せず、ONLY_FULL_GROUP_BY はデフォルトで有効になっていませんでした。5.7.5 より前の動作については、MySQL 5.6 リファレンス マニュアルを参照してください。) 標準 SQL への MySQL 拡張機能により、HAVING 句での参照が可能になります
        。選択リスト内のエイリアス式。MySQL 5.7.5 より前では、ONLY_FULL_GROUP_BY を有効にするとこの拡張機能が無効になるため、エイリアスなしの式を使用して HAVING 句を記述する必要がありました。MySQL 5.7.5 以降では、この制限が削除され、ONLY_FULL_GROUP_BY が有効かどうかに関係なく、HAVING 句でエイリアスを参照できるようになりました。
        詳しい説明と例については、セクション12.20.3「MySQL の GROUP BY の処理」を参照してください。

おすすめ

転載: blog.csdn.net/weixin_52255395/article/details/130929758