sql >> Databasteknik >  >> RDS >> SQLite

Hur man släpper en främmande nyckel i SQLite

Normalt om du behöver släppa en främmande nyckel i SQL, skulle du använda ALTER TABLE påstående. Men om du använder SQLite är det inte ett alternativ.

SQLite stöder en mycket begränsad delmängd av ALTER TABLE påstående. Det enda du kan göra med ALTER TABLE i SQLite byter man namn på en tabell, byter namn på en kolumn i en tabell eller lägger till en ny kolumn i en befintlig tabell.

Med andra ord kan du inte använda ALTER TABLE att släppa en främmande nyckel som du kan i andra RDBMS:er

Det rekommenderade sättet att "släppa" en främmande nyckel i SQLite är faktiskt att överföra data till en ny tabell utan en främmande nyckel (eller med en annan, om det är vad du behöver).

Det rekommenderade sättet

SQLite-dokumentationen rekommenderar en 12-stegsprocess för att göra schemaändringar i en tabell. Vi kommer att använda den processen för att "släppa" en främmande nyckel i följande exempel.

Skapa en tabell med en främmande nyckel

Låt oss först skapa en tabell med den främmande nyckeln och fylla i den med data.

CREATE TABLE Types( 
    TypeId INTEGER PRIMARY KEY, 
    Type
);

CREATE TABLE Pets( 
    PetId INTEGER PRIMARY KEY, 
    PetName,
    TypeId,
    FOREIGN KEY(TypeId) REFERENCES Types(TypeId)
);

INSERT INTO Types VALUES 
    ( NULL, 'Dog' ),
    ( NULL, 'Cat' ),
    ( NULL, 'Parakeet' ),
    ( NULL, 'Hamster' );

INSERT INTO Pets VALUES 
    ( NULL, 'Brush', 3 ),
    ( NULL, 'Tweet', 3 ),
    ( NULL, 'Yelp', 1 ),
    ( NULL, 'Woofer', 1 ),
    ( NULL, 'Fluff', 2 );

Här skapade jag faktiskt två tabeller och fyllde i dem med data. Två tabeller, eftersom den första (Typer ) har den primära nyckeln och den andra (Husdjur ) har den främmande nyckeln. Den främmande nyckeln lades till på den sista raden i den andra tabellen.

Vi kan verifiera att den främmande nyckeln skapades genom att köra följande kommando:

PRAGMA foreign_key_list(Pets);

Resultat:

 id  seq  table  from    to      on_update  on_delete  match
 --  ---  -----  ------  ------  ---------  ---------  -----
 0   0    Types  TypeId  TypeId  NO ACTION  NO ACTION  NONE  

Vi kan se detaljerna för den främmande nyckeln.

Låt oss nu "släppa" den främmande nyckeln.

”Släpp” den främmande nyckeln

Följande kod "släpper" den främmande nyckeln genom att skapa en ny tabell utan en främmande nyckel-begränsning, överföra data till den tabellen, släppa den ursprungliga tabellen och sedan byta namn på den nya tabellen till namnet på den ursprungliga tabellen.

PRAGMA foreign_keys = OFF;

BEGIN TRANSACTION;

CREATE TABLE Pets_new( 
    PetId INTEGER PRIMARY KEY, 
    PetName,
    TypeId
);

INSERT INTO Pets_new SELECT * FROM Pets;

DROP TABLE Pets;

ALTER TABLE Pets_new RENAME TO Pets;

COMMIT;

PRAGMA foreign_keys = ON;

Klart.

Om du behöver rekonstruera några index, utlösare eller vyer, gör det efter ALTER TABLE uttalande som byter namn på tabellen (strax före COMMIT ).

Låt oss nu kontrollera tabellen för främmande nyckelbegränsningar igen.

PRAGMA foreign_key_list(Pets);

Resultat:

 

(Det är tomt eftersom det inte finns några begränsningar för främmande nyckel i den här tabellen.)

Du kan använda samma metod för att lägga till en främmande nyckel till en befintlig tabell.

En alternativ metod

När du tittar på det föregående exemplet kanske du tänker att det finns ett mer effektivt sätt att göra det. Du kan till exempel göra så här:

PRAGMA foreign_keys = OFF;

BEGIN TRANSACTION;

ALTER TABLE Pets RENAME TO Pets_old;

CREATE TABLE Pets( 
    PetId INTEGER PRIMARY KEY, 
    PetName,
    TypeId
);

INSERT INTO Pets SELECT * FROM Pets_old;

DROP TABLE Pets_old;

COMMIT;

PRAGMA foreign_keys = ON;

Och det är sant. Med mitt exempel fungerar den här metoden lika bra.

Men den här metoden har också potential att korrumpera referenser till tabellen i alla befintliga triggers, vyer och främmande nyckelbegränsningar.

Så om din tabell redan har befintliga utlösare, vyer eller begränsningar för främmande nyckel, är det förmodligen säkrare att använda den rekommenderade metoden.


  1. Förbereda en MySQL- eller MariaDB-server för produktion - del ett

  2. UPPDATERA om det finns annat INSERT i SQL Server 2008

  3. Åtgärda dataförlust med logfrakt med försenad återställning

  4. psycopg2 motsvarighet till mysqldb.escape_string?