Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A better way to swap two primary key values and circumvent a ORA-00001: unique constraint violated?

Goal: Swap the primary keys of two records without encountering an ORA-00001: unique constraint violated. The solution that 'works' (further below) is just a silly hack. Is there a feature/technique to defer constraint enforcement until the transaction is committed?
As far as motivation - a legacy application that uses this data has a design flaw and relies on the IDs order and values - the request is to swap the PK values as follows:

BEFORE: 
388    English
389    French

AFTER:
389    English
388    French

What doesn't Work:

BEGIN
   UPDATE SPOKEN_LANGUAGES
      SET id = 388
    WHERE id = 389;

   UPDATE SPOKEN_LANGUAGES
      SET id = 389
    WHERE id = 388;
END;

Hack/Solution that 'works'

DECLARE
  V_MAGIC_NUMBER   NUMBER := 9999999;
BEGIN
  UPDATE SPOKEN_LANGUAGES
     SET id = 388 + V_MAGIC_NUMBER
   WHERE id = 389;

  UPDATE SPOKEN_LANGUAGES
     SET id = 389 + V_MAGIC_NUMBER
   WHERE id = 388;

  UPDATE SPOKEN_LANGUAGES
     SET id = id - V_MAGIC_NUMBER
   WHERE id = 389 + V_MAGIC_NUMBER;

  UPDATE SPOKEN_LANGUAGES
     SET id = id - V_MAGIC_NUMBER
   WHERE id = 388 + V_MAGIC_NUMBER;

END;

Table Definition:

CREATE TABLE SPOKEN_LANGUAGES
(
  ID             NUMBER(10)                     NOT NULL,
  LANGUAGE_NAME  VARCHAR2(40 BYTE)              NOT NULL
)

PK/UNIQUE INDEX:

   CREATE UNIQUE INDEX SL_PK ON SPOKEN_LANGUAGES    (ID)
like image 367
Brian Avatar asked Jan 25 '26 16:01

Brian


1 Answers

You need to do it in a single statement:

UPDATE SPOKEN_LANGUAGES
   SET id = case when id = 388 then 389 else 388 end
WHERE id in (388,389);

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!