PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

PostgreSQL - masukkan baris berdasarkan pilih dari tabel lain, dan perbarui FK di tabel itu dengan baris yang baru dimasukkan

Ada beberapa cara untuk menyelesaikan masalah.

1. menambahkan kolom untuk sementara

Seperti yang disebutkan orang lain, cara langsungnya adalah menambahkan kolom reminder_id untuk sementara ke dateset . Isi dengan IDs asli dari reminder meja. Gunakan untuk bergabung dengan reminder dengan dateset meja. Jatuhkan kolom sementara.

2. ketika awalnya unik

Jika nilai start kolom unik, Anda dapat melakukannya tanpa kolom tambahan dengan bergabung dengan reminder tabel dengan dateset tabel di start kolom.

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. saat awal tidak unik

Dimungkinkan untuk melakukannya tanpa kolom sementara bahkan dalam kasus ini. Ide utamanya adalah sebagai berikut. Mari kita lihat contoh ini:

Kami memiliki dua baris di reminder dengan start yang sama nilai dan ID 3 dan 7:

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

Setelah kita masukkan ke dalam dateset , akan ada ID baru yang dihasilkan, misalnya 1 dan 2:

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

Tidak masalah bagaimana kita menghubungkan dua baris ini. Hasil akhirnya bisa

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

atau

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

Kedua varian ini benar. Yang membawa kita ke solusi berikut.

Cukup masukkan semua baris terlebih dahulu.

INSERT INTO dateset (start)
SELECT start FROM reminder;

Cocokkan/gabungkan dua tabel di start kolom mengetahui bahwa itu tidak unik. "Jadikan" unik dengan menambahkan ROW_NUMBER dan bergabung dengan dua kolom. Dimungkinkan untuk membuat kueri lebih pendek, tetapi saya mengeja setiap langkah secara eksplisit:

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
;

Saya harap jelas dari kode apa fungsinya, terutama ketika Anda membandingkannya dengan versi yang lebih sederhana tanpa ROW_NUMBER . Jelas, solusi kompleks akan bekerja bahkan jika start unik, tetapi tidak seefisien solusi sederhana.

Solusi ini mengasumsikan bahwa dateset kosong sebelum proses ini.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hibernate 3.6.10 tidak menghapus secara kaskade melalui OneToMany JoinTable

  2. Performance Tuning:Buat indeks untuk kolom boolean

  3. Bagaimana cara menonaktifkan sementara batasan integritas db di Django - postgresql

  4. Praktik terbaik menangani hubungan antar tabel di Spring Data R2dbc

  5. Mengapa st_intersection mengembalikan non-poligon?