55

I want to do something like this:

DELETE FROM table WHERE id IN (SELECT ....)

How can I do that?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
ave4496
  • 2,950
  • 3
  • 21
  • 48
  • What database? In most, what you describe should just work. – Thilo Oct 28 '10 at 09:09
  • How can't you do that? What's not working? What database you using? Oracle/MySql/SqlServer? – Fermin Oct 28 '10 at 09:09
  • Clarify where will you get the Ids list from ..., yes it's possible to do delete where id in ... – A_Nabelsi Oct 28 '10 at 09:09
  • What's wrong with your code? It should work. – Max Oct 28 '10 at 09:09
  • 9
    `DELETE FROM table WHERE id IN (1,2,3,4)` or `DELETE FROM table WHERE id IN (SELECT id FROM table2 WHERE X=Y)` What do you really want to know? – Tim Schmelter Oct 28 '10 at 09:09
  • Your implementation should work – Ashwini Dhekane Oct 28 '10 at 09:10
  • Possible duplicate of [How to delete multiple rows in SQL where id = (x to y)](http://stackoverflow.com/questions/16029441/how-to-delete-multiple-rows-in-sql-where-id-x-to-y) – dodexahedron Oct 05 '15 at 09:06
  • This question really doesn't deserve the upvotes, as the OP obviously didn't even try it or even bother to google for it. What makes that more painfully obvious is that it's a duplicate of http://stackoverflow.com/questions/16029441/how-to-delete-multiple-rows-in-sql-where-id-x-to-y?rq=1 – dodexahedron Oct 05 '15 at 09:06
  • How can It be a duplicate when it was asked 3 years earlier? – ave4496 Feb 06 '17 at 08:00

4 Answers4

111

If you have to select the id:

 DELETE FROM table WHERE id IN (SELECT id FROM somewhere_else)

If you already know them (and they are not in the thousands):

 DELETE FROM table WHERE id IN (?,?,?,?,?,?,?,?)
Thilo
  • 257,207
  • 101
  • 511
  • 656
  • 5
    If they are in the thousands will that impact performance a lot? I am trying to remove some duplicates and some places I have between 2-3 duplicates. For other entries I might have a few hundred or thousands. – Zeliax Jun 20 '17 at 13:24
  • just confirmed this with DELETE FROM `user-access` WHERE `user-id`=5 AND `article-id` IN (14,7,8) , and want to add that the database did NOT care that there was no row with article-id 8, it just executed – clockw0rk Nov 08 '18 at 13:34
2

Disclaim: the following suggestion could be an overhead depending on the situation. The function is only tested with MSSQL 2008 R2 but seams be compatible to other versions

if you wane do this with many Id's you may could use a function which creates a temp table where you will be able to DELETE FROM the selection

how the query could look like:

-- not tested
-- @ids will contain a varchar with your ids e.g.'9 12 27 37'
DELETE FROM table WHERE id IN (SELECT i.number FROM iter_intlist_to_tbl(@ids))

here is the function:

ALTER FUNCTION iter_intlist_to_tbl (@list nvarchar(MAX))
   RETURNS @tbl TABLE (listpos int IDENTITY(1, 1) NOT NULL,
                       number  int NOT NULL) AS

   -- funktion gefunden auf http://www.sommarskog.se/arrays-in-sql-2005.html
   -- dient zum übergeben einer liste von elementen

BEGIN
    -- Deklaration der Variablen
    DECLARE @startpos int,
            @endpos   int,
            @textpos  int,
            @chunklen smallint,
            @str      nvarchar(4000),
            @tmpstr   nvarchar(4000),
            @leftover nvarchar(4000)

    -- Startwerte festlegen
   SET @textpos = 1
   SET @leftover = ''

   -- Loop 1
    WHILE @textpos <= datalength(@list) / 2
    BEGIN

        --
        SET @chunklen = 4000 - datalength(@leftover) / 2 --datalength() gibt die anzahl der bytes zurück (mit Leerzeichen)

        --
        SET @tmpstr = ltrim(@leftover + substring(@list, @textpos, @chunklen))--SUBSTRING ( @string ,start , length ) | ltrim(@string) abschneiden aller Leerzeichen am Begin des Strings

        --hochzählen der TestPosition
        SET @textpos = @textpos + @chunklen

        --start position 0 setzen
        SET @startpos = 0

        -- end position bekommt den charindex wo ein [LEERZEICHEN] gefunden wird
        SET @endpos = charindex(' ' COLLATE Slovenian_BIN2, @tmpstr)--charindex(searchChar,Wo,Startposition)

        -- Loop 2
        WHILE @endpos > 0
        BEGIN
            --str ist der string welcher zwischen den [LEERZEICHEN] steht
            SET @str = substring(@tmpstr, @startpos + 1, @endpos - @startpos - 1) 

            --wenn @str nicht leer ist wird er zu int Convertiert und @tbl unter der Spalte 'number' hinzugefügt
            IF @str <> ''
                INSERT @tbl (number) VALUES(convert(int, @str))-- convert(Ziel-Type,Value)

            -- start wird auf das letzte bekannte end gesetzt
            SET @startpos = @endpos

            -- end position bekommt den charindex wo ein [LEERZEICHEN] gefunden wird
            SET @endpos = charindex(' ' COLLATE Slovenian_BIN2, @tmpstr, @startpos + 1)
        END
        -- Loop 2

        -- dient dafür den letzten teil des strings zu selektieren
        SET @leftover = right(@tmpstr, datalength(@tmpstr) / 2 - @startpos)--right(@string,anzahl der Zeichen) bsp.: right("abcdef",3) => "def"
    END
    -- Loop 1

    --wenn @leftover nach dem entfernen aller [LEERZEICHEN] nicht leer ist wird er zu int Convertiert und @tbl unter der Spalte 'number' hinzugefügt
    IF ltrim(rtrim(@leftover)) <> ''
        INSERT @tbl (number) VALUES(convert(int, @leftover))

    RETURN
END


    -- ############################ WICHTIG ############################
    -- das is ein Beispiel wie man die Funktion benutzt
    --
    --CREATE    PROCEDURE get_product_names_iter 
    --      @ids varchar(50) AS
    --SELECT    P.ProductName, P.ProductID
    --FROM      Northwind.Products P
    --JOIN      iter_intlist_to_tbl(@ids) i ON P.ProductID = i.number
    --go
    --EXEC get_product_names_iter '9 12 27 37'
    --
    -- Funktion gefunden auf http://www.sommarskog.se/arrays-in-sql-2005.html
    -- dient zum übergeben einer Liste von Id's
    -- ############################ WICHTIG ############################
WiiMaxx
  • 5,322
  • 8
  • 51
  • 89
2
Delete from BA_CITY_MASTER where CITY_NAME in (select CITY_NAME from BA_CITY_MASTER group by CITY_NAME having count(CITY_NAME)>1);
Ram Sharma
  • 8,676
  • 7
  • 43
  • 56
rahulnikhare
  • 1,362
  • 1
  • 18
  • 25
  • You should format your code by selecting it and hitting ctrl-k. Also, it helps to provide some explanation, perhaps suggesting what was wrong with the code in the question (if anything). – Tom Fenech Feb 21 '14 at 11:41
  • 1
    This is a great solution: `DELETE FROM [TableName] WHERE [ColumnName] IN (SELECT [ColumnName] FROM [TableName] GROUP BY [ColumnName] HAVING COUNT([ColumnName])>1);` – dakab Apr 14 '14 at 09:49
-4
  • You can make this.

    CREATE PROC [dbo].[sp_DELETE_MULTI_ROW]
    @CODE XML ,@ERRFLAG CHAR(1) = '0' OUTPUT

AS

SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

DELETE tb_SampleTest WHERE CODE IN( SELECT Item.value('.', 'VARCHAR(20)') FROM @CODE.nodes('RecordList/ID') AS x(Item) )

IF @@ROWCOUNT = 0 SET @ERRFLAG = 200

SET NOCOUNT OFF

  • <'RecordList'><'ID'>1<'/ID'><'ID'>2<'/ID'><'/RecordList'>
ThienPhuc
  • 1
  • 3