Depois de buscar todos os resultados em seu loop de execução, você deve obter o próximo conjunto de linhas e fechar o cursor antes de tentar executar o procedimento armazenado novamente. Tente isto:
foreach($data_arr AS $key => $val){
$values = $val;
$stmt->execute();
$res = $stmt->fetchAll();
$stmt->nextRowset(); // NEW: Get the next rowset after fetching your results
$stmt->closeCursor(); // NEW: Close the cursor
}
A adição realmente importante aqui é a chamada para nextRowSet() . Nos bastidores, o PDO está retornando um segundo conjunto de linhas que você precisa acessar antes de executar um segundo procedimento armazenado (e subsequente) na mesma conexão.