sql >> Databáze >  >> RDS >> PostgreSQL

PostgreSQL - vložit řádky na základě výběru z jiné tabulky a aktualizovat FK v této tabulce nově vloženými řádky

Existuje několik způsobů, jak problém vyřešit.

1. dočasně přidat sloupec

Jak již zmínili ostatní, přímým způsobem je dočasné přidání sloupce reminder_id na dateset . Naplňte jej původními IDs z reminder stůl. Použijte jej k připojení k reminder s dateset stůl. Zrušte dočasný sloupec.

2. kdy je start jedinečný

If hodnoty start sloupec je jedinečný, lze to provést bez dalšího sloupce spojením reminder tabulka s dateset tabulky na start sloupec.

INSERT INTO dateset (start)
SELECT start FROM reminder;

WITH
CTE_Joined
AS
(
    SELECT
        reminder.id AS reminder_id
        ,reminder.dateset_id AS old_dateset_id
        ,dateset.id AS new_dateset_id
    FROM
        reminder
        INNER JOIN dateset ON dateset.start = reminder.start
)
UPDATE CTE_Joined
SET old_dateset_id = new_dateset_id
;

3. kdy start není jedinečný

I v tomto případě to lze provést bez dočasného sloupce. Hlavní myšlenka je následující. Podívejme se na tento příklad:

V reminder máme dva řádky se stejným start hodnota a ID 3 a 7:

reminder
id    start         dateset_id
3     2015-01-01    NULL
7     2015-01-01    NULL

Poté, co je vložíme do dateset , budou vygenerována nová ID, například 1 a 2:

dateset
id    start
1     2015-01-01
2     2015-01-01

Nezáleží na tom, jak tyto dva řádky propojíme. Konečný výsledek by mohl být

reminder
id    start         dateset_id
3     2015-01-01    1
7     2015-01-01    2

nebo

reminder
id    start         dateset_id
3     2015-01-01    2
7     2015-01-01    1

Obě tyto varianty jsou správné. Což nás přivádí k následujícímu řešení.

Jednoduše nejprve vložte všechny řádky.

INSERT INTO dateset (start)
SELECT start FROM reminder;

Spojte/spojte dva stoly na start sloupec s vědomím, že není jedinečný. „Udělejte to“ jedinečným přidáním ROW_NUMBER a spojení dvěma sloupci. Dotaz je možné zkrátit, ale každý krok jsem výslovně uvedl:

WITH
CTE_reminder_rn
AS
(
    SELECT
        id
        ,start
        ,dateset_id
        ,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
    FROM reminder
)
,CTE_dateset_rn
AS
(
    SELECT
        id
        ,start
        ,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
    FROM dateset
)
,CTE_Joined
AS
(
    SELECT
        CTE_reminder_rn.id AS reminder_id
        ,CTE_reminder_rn.dateset_id AS old_dateset_id
        ,CTE_dateset_rn.id AS new_dateset_id
    FROM
        CTE_reminder_rn
        INNER JOIN CTE_dateset_rn ON 
            CTE_dateset_rn.start = CTE_reminder_rn.start AND
            CTE_dateset_rn.rn = CTE_reminder_rn.rn
)
UPDATE CTE_Joined
SET old_dateset_id = new_dateset_id
;

Doufám, že z kódu je jasné, co dělá, zvláště když to porovnáte s jednodušší verzí bez ROW_NUMBER . Je zřejmé, že komplexní řešení bude fungovat, i když start je unikátní, ale není tak efektivní jako jednoduché řešení.

Toto řešení předpokládá, že dateset je před tímto procesem prázdný.



  1. Zabezpečení php api pro použití v aplikaci pro Android

  2. Databáze MySQL nelze spustit na XAMPP pro Mac

  3. Jak zastavím více e-mailů NEBO uživatelské jméno?

  4. Vytvořte sekvenci pomocí START WITH z Query