Search code examples
sqlsqlitesqlitestudio

SQLite before insert trigger


I'm trying to insert duplicates data to table B when PKA violated using a BEFORE INSERT TRIGGER as the following example:

CREATE TABLE A( Col INTEGER, Coll TEXT(25), CONSTRAINT PKA PRIMARY KEY(Col, Coll) ON CONFLICT IGNORE);
CREATE UNIQUE INDEX IX_A ON A(Col, Coll);

CREATE TABLE B( Col INTEGER, Coll TEXT(25));
CREATE INDEX IX_B ON B(Col, Coll);

CREATE TRIGGER Trig
BEFORE INSERT
ON A
WHEN (Col = New.Col AND Coll = New.Coll)
BEGIN
      INSERT INTO B(Col, Coll) VALUES(New.Col, New.Coll);
END;

But, it seems like the column Col is not accessible there, so it throws:

no such column: Col

Even when I change the conditions to

New.Col IN(SELECT Col FROM A)
AND
New.Coll IN(SELECT Coll FROM A)

I get another error message:

UNIQUE constraint failed: A.Col, A.Coll

While it shouldn't because of ON CONFLICT IGNORE.

  • Why did I get those error messages? (What's the cause).
  • How can I use the trigger to insert duplicates into another table?

Solution

  • You don't need the index:

    CREATE UNIQUE INDEX IX_A ON A(Col, Coll);
    

    because you have already defined (Col, Coll) as the PRIMARY KEY and furthermore, with this index, although you have ON CONFLICT IGNORE defined for a duplicate row, you will receive an error if you try to insert a duplicate row, because ON CONFLICT IGNORE is not defined for the index.
    So drop it:

    DROP INDEX IF EXISTS IX_A;
    

    Now, change the code of the trigger to this:

    CREATE TRIGGER Trig
    BEFORE INSERT
    ON A
    WHEN EXISTS (SELECT 1 FROM A WHERE Col = New.Col AND Coll = New.Coll)
    BEGIN
          INSERT INTO B(Col, Coll) VALUES(New.Col, New.Coll);
    END;
    

    EXISTS checks the table A if it already contains a row with column values the same as the ones to be inserted and if it does then the new row is inserted in table B.

    You could also write the trigger like this:

    CREATE TRIGGER Trig
    BEFORE INSERT
    ON A
    BEGIN
          INSERT INTO B(Col, Coll)
          SELECT Col, Coll FROM A
          WHERE (Col, Coll) = (New.Col, New.Coll);
    END;