Sharepoint - Update/Delete All List-item in SharePoint online list with more than 30,000 records

Querying data from SharePoint using CSOM works in batches. Every time you call ExecuteQuery() all operations are batched to one transaction and sent to the SharePoint. The key is to use ExecuteQuery() only when needed.

You can use CamlQuery and limit number of retrieving items.

Delete all items

$cc = New-Object Microsoft.SharePoint.Client.ClientContext("https://tenant.sharepoint.com/sites/some-site")
$cc.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials("[email protected]", (ConvertTo-SecureString "password" -AsPlainText -Force))

$list = $cc.Web.Lists.GetByTitle("Some list")
$query = New-Object Microsoft.SharePoint.Client.CamlQuery
$query.ViewXml = "<View><RowLimit>200</RowLimit></View>"

do
{
    $started = Get-Date
    $items = $list.GetItems($query)
    $cc.Load($items)
    $cc.ExecuteQuery()

    if ($items.Count -eq 0) { break }

    for ($i = 0; $i -lt $items.Count; $i++)
    {
        # Delete row 
        # Because DeleteObject() effectively change the collection the index 0 is not a mistake
        $items[0].DeleteObject()
    }

    $cc.ExecuteQuery()
    Write-Host "Time elapsed: $((Get-Date) - $started)"
} while ($true)

Update all items

$cc = New-Object Microsoft.SharePoint.Client.ClientContext("https://tenant.sharepoint.com/sites/some-site")
$cc.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials("[email protected]", (ConvertTo-SecureString "password" -AsPlainText -Force))

$list = $cc.Web.Lists.GetByTitle("Some list")
$query = New-Object Microsoft.SharePoint.Client.CamlQuery
$query.ViewXml = "<View><RowLimit>200</RowLimit></View>"

do
{
    $started = Get-Date
    $items = $list.GetItems($query)
    $cc.Load($items)
    $cc.ExecuteQuery()

    # It is important to update ListItemCollectionPosition of object $query with current position
    $query.ListItemCollectionPosition = $items.ListItemCollectionPosition

    if ($items.Count -eq 0) { break }

    for ($i = 0; $i -lt $items.Count; $i++)
    {
        # update columns as needed
        $items[$i].Update()
    }

    $cc.ExecuteQuery()
    Write-Host "Time elapsed: $((Get-Date) - $started)"
    # ListItemCollectionPosition is null if there is no other page
} while ($query.ListItemCollectionPosition -ne $null)