Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

martinszeltins's avatar

100k rows with() eager loading result in - too many SQL parameters?

I noticed that when I eager load the Posts with comments it makes an interesting query using WHERE IN. But SQL has parameter limit of 65535 (at least my old Postgres server does).

So what happens when we try to query for 100k rows and eager load a related table like comments?

  $posts = Post::with('comments')->get()

It will end up with 2 queries like this

select * from posts
select * from comments where comments.post_id in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 ......... 100000)

In which case, wouldn't we get this error? So is this a flaw in Laravel's eloquent?

Failed to execute the SQL statement: SQLSTATE[HY000]: General error: 7 number of parameters must be between 0 and 65535.
0 likes
14 replies
martinszeltins's avatar

@STAUDENMEIR - I'm using Laravel 5.7 with php 7.2 and postgresql 9.3

It looks like PDO stores the number of request parameters in an immutable int, so it cannot be more than 65,535 for some reason.

I don't know if anyone has run into this problem. It looks like the solution could be to split the query in smaller chunks.

martinszeltins's avatar

5.7.20

It doesn't look like Laravel is the problem but rather it seems to be a limitation of PHP's PDO.

martinszeltins's avatar

Can you explain what you mean that it doesn't use bindings? How does it eager load it?

I have debugbar installed so I looked at the actual queries executed and this is what it shows

select * from `posts` order by `i_date` desc limit 10 offset 0

select * from `comments` where `comments`.`post_id` in (1, 2, 3, 4, 5, 9, 10, 11, 12, 13) order by `id` desc

Post model

public function comments()
{
     return $this->hasMany('App\Models\Comments', 'post_id', 'id')->orderBy('id', 'desc');
}

Comments model is a just plain Model.

staudenmeir's avatar

Normally, Laravel use prepared statements with bindings:

Comment::find(1);

select * from `comments` where `id` = ? limit 1 // Bindings: [1]

Since Laravel 5.7.14, eager loading puts integer keys directly in the query:

select * from `comments` where `comments`.`post_id` in (1, 2, 3)

This way, errors like yours shouldn't be possible anymore.

staudenmeir's avatar

Are you actually getting this error? Or are you asking a theoretical question?

martinszeltins's avatar

@STAUDENMEIR - I just ran a test and I got the error.

Route::get('test', function () {
        
        ini_set('memory_limit', '2G');

        $posts = \App\Models\Post::select('id')->take(70000)->get();
        $comments = \App\Models\Comments::whereIn('post_id', $posts->pluck('id'))->get();

        return $comments->first();
    });

It gave me this error

Illuminate \ Database \ QueryException (HY000)

"SQLSTATE[HY000]: General error: 7 number of parameters must be between 0 and 65535 (SQL: select * from "comments" where "post_id" in (149519, 142920, 147987, 147045, 148070, 142797, 149327, 142862, 142681, 167789, 142910, 143819, 142077, 145681, 140397, 142351, 141390, 143577, 149932, 141714, 140597, 142972, 149902, 142817, 142542, 149336, 140365, 142613, 142209, 140590, 147231, 142969, 142950, 147842, 141567, 140501, 149357, 141789, 145979, 147125, 143841, 145495, 149812, 141522, 148000, 141616, 140843, 149852, 142980, 143532, 149581, 141434, 149312, 149811, 149214, 149161, 142793, 140529, 147594, 142061, 149179, 143644, 142547, 143881, 140968, 145448, 142661, 142370, 145784, 143733, 142106, 149305, 141896, 143218, 146113, 140342, 149275, 142605, 147943, 147041, 142809, 140268, 140162, 140265, 140300, 140288, 140303, 141860, 140304, 140325, 140354, 140356, 140372, 149320, 140402, 140410, 140412, 140416, 149255, 140422, 140431, 140481, 140492, 140508, 140539, 140556, 140573, 174651, 140577, 140639, 140640, 140668, 145462, 140687, 140697, 140700, 140717, 141722, 140725, 140727, 140742, 140759, 140814, 141637, 140822, 140858, 140862, 149332, 149331, 140873, 149314, 140876, 149291, 149290, 140877, 140887, 140888, 140913, 140914, 174520, 140920, 140923, 140931, 140939, 160881, 140949, 140944...................................
staudenmeir's avatar

whereIn() still relies on bindings (as it should), but eager loading now uses whereIntegerInRaw() for integer keys.

martinszeltins's avatar

@STAUDENMEIR - Oh I see, so I shouldn't use whereIn() with more than 65k bindings? But instead use eager loading when possible?

Tray2's avatar

Open a new thread and ask your question. Supply information about your tables and the code used to fetch the data. Then we should be able to help you.

Please or to participate in this conversation.