🍑

[PHP×SQL]where句のinを指定した長さ以内で分割する

2022/08/26に公開

where句のinを指定した長さ以内で分割するサンプルコードです
クエリ長が長すぎて、エラーが発生し処理を実行できなくなる場合や、データベースへの負荷を分散したい場合などに

コード

where句のinを分割するパーツのみ書きます

<?php

// メモリ設定: 環境に合わせて適宜変更
ini_set('memory_limit','256M');

// where句のin
$inSql='123,4567,8910,11,121314,15,16171819,20,21,222324,2526272829,3031,32,33343536,3738,3940,41,424344,4546,47,484950,51,52,5354555657,585960,61';

// where句のin最大長(単位: バイト)
$maxLen=35;

$inSqlLen=strlen($inSql);

echo $inSqlLen.PHP_EOL;

$arr=[];
$i=0;

while(true){
	$inSqlToLast=substr($inSql,$i);
	if(strlen($inSqlToLast)<= $maxLen){
		array_push($arr,$inSqlToLast);
		break;
	}else{
		// where句のinをi番目から最大長分切り取り
		$inSqlAfter=substr($inSql,$i,$maxLen);
		// 切り取リ結果のいちばん後ろの「,」の位置を取得
		$place=strrpos($inSqlAfter,',');
		// 切り取り結果の先頭から「,」のひとつ前の文字までを取得
		$result=substr($inSqlAfter,0,$place);
		array_push($arr,$result);
	}
	// 先頭の 「,」をスキップするため、+1する
	$i=$i+$place+1;
}

// 結果確認
var_dump($arr);

ポイント

substrでまず最大長分切り出した後、strrposでいちばん後ろの「,」の位置を求めること

実際の用途

BigQueryで実行したクエリが1024KBを超えてエラーになってしまったため、その対処として上記処理を書きました

実際に発生したエラー

{
  "error": {
    "code": 400,
    "message": "The query is too large. The maximum standard SQL query length is 1024.00K characters, including comments and white space characters.",
    "errors": [
      {
        "message": "The query is too large. The maximum standard SQL query length is 1024.00K characters, including comments and white space characters.",
        "domain": "global",
        "reason": "invalid"
      }
    ],
    "status": "INVALID_ARGUMENT"
  }
}

参考

Discussion