77

What is the most efficient way to delete all the items of a large list in SharePoint? The code should take Query throttling limits into consideration.

2
  • If you want to delete all the items in the list, delete the list and create a new list with same name. Commented Jun 3, 2017 at 0:25
  • 1
    That does not work if the list has workflows attached. Commented Jun 9, 2017 at 10:08

12 Answers 12

55

The most efficient way to a lot of transaction in SharePoint is using of SPWeb.ProcessBatchData method. For deleting operations there are very helpfull post. Code exaple from that post:

    // We prepare a String.Format with a String.Format, this is why we have a {{0}} 
   string command = String.Format("<Method><SetList Scope=\"Request\">{0}</SetList><SetVar Name=\"ID\">{{0}}</SetVar><SetVar Name=\"Cmd\">Delete</SetVar><SetVar Name=\"owsfileref\">{{1}}</SetVar></Method>", list.ID);
   // We get everything but we limit the result to 100 rows 
   SPQuery q = new SPQuery();
   q.RowLimit = 100;

   // While there's something left 
   while (list.ItemCount > 0)
   {
    // We get the results 
    SPListItemCollection coll = list.GetItems(q);

    StringBuilder sbDelete = new StringBuilder();
    sbDelete.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Batch>");

    Guid[] ids = new Guid[coll.Count];
    for (int i=0;i<coll.Count;i++)
    {
     SPListItem item = coll[i];
     sbDelete.Append(string.Format(command, item.ID.ToString(), item.File.ServerRelativeUrl));
     ids[i] = item.UniqueId;
    }
    sbDelete.Append("</Batch>");

    // We execute it 
    web.ProcessBatchData(sbDelete.ToString());

    //We remove items from recyclebin
    web.RecycleBin.Delete(ids);

    list.Update();
   }
  }
7
  • 16
    Cannot resist mentioning, that this will move items to recycle bin instead of actually deleting them. Commented Jan 10, 2012 at 11:40
  • 1
    Didn't think of that. Nice catch.
    – Dennis G
    Commented Jan 10, 2012 at 12:25
  • 3
    Thanks for remark! I updated code with batch deleting items from recycle bin.
    – IAfanasov
    Commented Jan 10, 2012 at 12:30
  • 1
    @Tom Resing we used this method in same scenario: list contains thousands items (in production it can grow to dozens of thousands) and per one operation we needed to delete hundreds items. We didn't measure perfomance, but it noticeably increased.
    – IAfanasov
    Commented Jan 11, 2012 at 6:11
  • 2
    @IAfanasov - user8217 is right, there is a problem here. You delete the items from the recycle bin based on their old ID, but after they were deleted they get a new ID, so the code fails.
    – banana
    Commented Aug 22, 2013 at 9:15
33

I took a stab at converting IAfanasov's answer into PowerShell. Seems to work for me, but would be interested in any feedback.

[System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
[System.Reflection.Assembly]::Load("Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
[System.Reflection.Assembly]::Load("Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
[System.Reflection.Assembly]::Load("System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")

write-host 

# Enter your configuration here
$siteUrl = "http://mysharepointsite.example.com/"
$listName = "Name of my list"
$batchSize = 1000

write-host "Opening web at $siteUrl..."

$site = new-object Microsoft.SharePoint.SPSite($siteUrl)
$web = $site.OpenWeb()
write-host "Web is: $($web.Title)"

$list = $web.Lists[$listName];
write-host "List is: $($list.Title)"

while ($list.ItemCount -gt 0)
{
  write-host "Item count: $($list.ItemCount)"

  $batch = "<?xml version=`"1.0`" encoding=`"UTF-8`"?><Batch>"
  $i = 0

  foreach ($item in $list.Items)
  {
    $i++
    write-host "`rProcessing ID: $($item.ID) ($i of $batchSize)" -nonewline

    $batch += "<Method><SetList Scope=`"Request`">$($list.ID)</SetList><SetVar Name=`"ID`">$($item.ID)</SetVar><SetVar Name=`"Cmd`">Delete</SetVar><SetVar Name=`"owsfileref`">$($item.File.ServerRelativeUrl)</SetVar></Method>"

    if ($i -ge $batchSize) { break }
  }

  $batch += "</Batch>"

  write-host

  write-host "Sending batch..."

  # We execute it 
  $result = $web.ProcessBatchData($batch)

  write-host "Emptying Recycle Bin..."

  # We remove items from recyclebin
  $web.RecycleBin.DeleteAll()

  write-host

  $list.Update()
}

write-host "Done."
2
  • 1
    Very Helpful and instructive
    – Iman
    Commented Jul 12, 2014 at 9:22
  • This only works if you want to delete ALL items correct? What if we only want to delete all items in a particular view, or based on a criteria such as Title? I'm still pretty intermediate with PowerShell, if that; esp. WRT SharePoint.
    – Chiramisu
    Commented Jan 19, 2018 at 19:26
25

I like IAfanasov's response. ProcesBatchData is the way to go.

But you are asking about the "most efficient way to delete all the items of a large list". The most efficient way is to delete the list and re-create it, if you really want to delete all items. It will be a lot quicker than doing any iterative actions.

6
  • 12
    This approach is definitely acceptable in some cases, but you should take into account, that the lookup fields, which point to the deleted list, will be broken. Also, all the list views will be removed from all pages and from all sites. Commented Jan 10, 2012 at 11:42
  • 6
    Would it help to save the list as a template and NOT include the content? That should save the columns and views and permissions and so on...
    – AlexPoint
    Commented Jan 10, 2012 at 12:02
  • 2
    @AlexPoint & omlin both correct. Saving the list as a template should take care of columns, views, permissions etc. - but sometimes it doesn't work, so I would first try it out before deleting the old list completely.
    – Dennis G
    Commented Jan 10, 2012 at 12:24
  • I came here to suggest the template option without content. That seems like it's at least worth a shot before running some code.
    – Mike
    Commented May 25, 2017 at 16:04
  • @DennisG: Saving a list as a list template does not include permissions. Exporting the list via Export-SPWeb -IncludeUserSecurity (you can restrict the export to your list via -ItemUrl "lists/YourList") "preserves the user security settings except for SPLists that have broken inheritance and item level permissions set", but the list will be re-created using a new ID, so lookup fields referencing the list will be still broken.
    – pholpar
    Commented Jul 7, 2017 at 12:08
9

In addition to IAfanosov's solution, I've written a method to clear the recycle bin from all items that were deleted from the given list:

/// <summary>
/// Deletes all items from the recycle bin in a web that originally came from the given list
/// </summary>
/// <param name="sourceList">List where the items originated from</param>
private static void TruncateRecycleBin(SPList sourceList)
{
    Console.WriteLine("Truncating recycle bin of all items deleted from list [{0}]", sourceList.Title);

    SPRecycleBinItemCollection recycleBin = sourceList.ParentWeb.RecycleBin;
    List<Guid> itemsToDelete = new List<Guid>();
    for (int i = 0; i < recycleBin.Count; i++)
    {
        // Only delete items from this specific list
        if (recycleBin[i].DirName.StartsWith(sourceList.RootFolder.ServerRelativeUrl.ToString()))
        {
            itemsToDelete.Add(recycleBin[i].ID);
        }
    }

    Console.WriteLine("About to delete [{0}] items from recycle bin...", itemsToDelete.Count);
    if (itemsToDelete.Count > 0)
    {
        recycleBin.Delete(itemsToDelete.ToArray());
    }

    Console.WriteLine("Done truncating recycle bin.");
}
1
  • 1
    Thanks Mark, that works great! Just 1 glitch. You will have to replace if (recycleBin[i].DirName.StartsWith(sourceList.RootFolder.ToString())) with if(recycleBin[i].DirName.StartsWith(sourceList.RootFolder.ServerRelativeUrl.Substring(1))) for it to work on a list in a subsite.
    – Ajay
    Commented Aug 29, 2014 at 22:52
7

Navigate to DATA SHEET VIEW (List tools > List > data sheet view)

Just select & delete all the rows in the sheet and move back to STANDARD VIEW.

Does this sounds like an effective way using UI ?

1
  • 2
    For thousands of list items? No. For 10s of thousands of lists items? Definitely not.
    – Underverse
    Commented Aug 16, 2016 at 7:54
5

PowerShell is the way to go. The following will parse 500 items at a time into the recycle bin and then remove them from the recycle bin. I've used this on lists up to 700k items.

# Enter your configuration here
$siteUrl = "http://sitecollectionurl"
$listName = "Name of List"
$batchSize = 500

write-host "Opening web at $siteUrl..."

$site = new-object Microsoft.SharePoint.SPSite($siteUrl)
$web = $site.OpenWeb()
write-host "Web is: $($web.Title)"

$list = $web.Lists[$listName];
write-host "List is: $($list.Title)"

while ($list.ItemCount -gt 0)
{
  write-host "Item count: $($list.ItemCount)"

  $batch = "<?xml version=`"1.0`" encoding=`"UTF-8`"?><Batch>"
  $i = 0

  foreach ($item in $list.Items)
  {
    $i++
    write-host "`rProcessing ID: $($item.ID) ($i of $batchSize)" -nonewline

    $batch += "<Method><SetList Scope=`"Request`">$($list.ID)</SetList><SetVar Name=`"ID`">$($item.ID)</SetVar><SetVar Name=`"Cmd`">Delete</SetVar><SetVar Name=`"owsfileref`">$($item.File.ServerRelativeUrl)</SetVar></Method>"

    if ($i -ge $batchSize) { break }
  }

  $batch += "</Batch>"

  write-host

  write-host "Sending batch..."

  # We execute it 
  $result = $web.ProcessBatchData($batch)

  write-host "Emptying Recycle Bin..."

  # We remove items from recyclebin
  $web.RecycleBin.DeleteAll()

  write-host

  $list.Update()
}

write-host "Done."

I did see some formatting errors when copying into the forum but the script is solid.

5

I know this is old but...

Easiest way for me is to open in access view,

  • Select "Link to data on the SharePoint site"
  • Select all items and "Delete"
  • Save changes to SharePoint site

DONE :)

2
#Check and add SharePoint PowerShell snap-in
if(-not(
Get-PSSnapin | Where { $_.Name -eq "Microsoft.SharePoint.PowerShell"})
) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$SITEURL = "http://sitename"

$site = new-object Microsoft.SharePoint.SPSite ( $SITEURL )
$web = $site.OpenWeb()

$oList = $web.Lists["Catering Consumption"];

$collListItems = $oList.Items;
$count = $collListItems.Count - 1

for($intIndex = $count; $intIndex -gt -1; $intIndex--)
{
    $collListItems.Delete($intIndex);
} 

above method might be slow in bigger lists, to delete bigger lists faster, you can go for below method

Get-SPWeb $FooUrl | % { $_.Lists.Delete([System.Guid]$_.Lists["Catering Consumption"].ID) }

Please note in above example list name is : Catering Consumption

2

What about linking to the list in Access, then doing a SQL query: DELETE * FROM [MyTable] ?

0
0

The answers below were certainly helpful. However, for those that are not "programmer" savvy, there is another way using Microsoft Access (part of the Office365 suite), but it's painfully slow, and it removes the record and it does not put it into the recycle bin.

I had over 130,000 records in one list I created by accident. I used this method, by basically setting it to run and forgot about it. Next morning, all the records were gone and I was able to delete the List, without any errors.

  1. Open the MS Access app

  2. Goto External Data

  3. New data source...

  4. From Online Services...Sharepoint List

  5. Fill in the requirements in the form

  6. Make sure you've chosen the Link to the Data Source option

  7. Select the list in question (if more than one)

  8. Next, open a New Query window in Access

  9. Type the DELETE sql command for the linked table:

    DELETE [myList] FROM [myList];

Run the query.

-1

All you have to do is create a datasheet view with no filter, select all rows, and hit the delete button.

2
  • 1
    How well does that work when you are dealing with large lists? Lets say 50K+ items. Good luck Commented Apr 12, 2017 at 1:50
  • I don't know. I think as long as the list displays in datasheet view, it would work. However, I would expect it to take a long time and to cause database locks during that time.
    – Erin L
    Commented Apr 12, 2017 at 13:57
-1

Maybe You can use this code:

protected void Page_Load(object sender, EventArgs e)
{
    SPSite site = new SPSite([Sharepoint Server]);
    SPWeb web = site.OpenWeb();
    web.AllowUnsafeUpdates = true;
    SPList list = web.Lists[List Name];

    deleteAllRerecords(list);
    web.Update();

}

public void deleteAllRerecords(SPList list)
{
    SPListItemCollection items = list.Items;
    for (int i = items.Count - 1; i >= 0; i--)
    {
        items[i].Delete();
    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.