How to delete multiple rows with 2 columns as composite primary key in SQLite? How to delete multiple rows with 2 columns as composite primary key in SQLite? sqlite sqlite

How to delete multiple rows with 2 columns as composite primary key in SQLite?


First, find out which rows you want to delete.The easiest way is with a join:

SELECT *FROM apt_langJOIN (SELECT 42122 AS apt_fk, 'en' AS apt_lang_fk UNION ALL      SELECT 42123          , 'es'                UNION ALL      SELECT 42123          , 'en'                         )USING (apt_fk, apt_lang_fk)

To use this with a DELTE, either check with EXISTS for a match:

DELETE FROM apt_langWHERE NOT EXISTS (SELECT 1                  FROM apt_lang AS a2                  JOIN (SELECT 42122 AS apt_fk, 'en' AS apt_lang_fk UNION ALL                        SELECT 42123          , 'es'                UNION ALL                        SELECT 42123          , 'en'                         )                  USING (apt_fk, apt_lang_fk)                  WHERE apt_fk      = apt_lang.apt_fk                    AND apt_lang_fk = apt_lang.apt_lang_fk)

or get the ROWIDs of the subquery and check against those:

DELETE FROM apt_langWHERE rowid NOT IN (SELECT apt_lang.rowid                    FROM apt_lang                    JOIN (SELECT 42122 AS apt_fk, 'en' AS apt_lang_fk UNION ALL                          SELECT 42123          , 'es'                UNION ALL                          SELECT 42123          , 'en'                         )                    USING (apt_fk, apt_lang_fk))


This should work:

DELETE FROM apt_lang WHERE (apt_fk, apt_lang_fk) NOT IN (VALUES (42122,"en"),(42123,"es"),(42123,"en"))


Yes, it's possible to delete rows from SQLite based on a subquery that builds on multiple columns. This can be done with SQLite's concatenate "||" operator. It might help to show an example.

Setup:

create table a (x,y); insert into a values ('A','B');insert into a values ('A','C');create table b (x,y);insert into b values ('A','C');insert into b values ('A','X');

Show Tables:

select * from a;A|BA|Cselect * from b;A|CA|X

Assuming you want to delete from table a rows where column x and column y don't match with table b, the following select will accomplish that.

delete from a where x||y not in (select a.x||a.y from a,b where a.x=b.x and a.y=b.y);

Result:

select * from a;A|B

Summary

This relies on concatenating several columns into one with the "||" operator. Note, it will work on calculated values too, but it might require casting the values. So, just a few conversions to note with the "||" operator...

 select 9+12|| 'test'; 21 -- Note we lost 'test' select cast(9+12 as text)|| 'test'; 21test -- Good!  'test' is there.