Postgresql 10 - So ordnen Sie eine Primärschlüsselspalte in einer Tabelle neu an, die von anderen Tabellen abhängt

Postgresql 10 - So ordnen Sie eine Primärschlüsselspalte in einer Tabelle neu an, die von anderen Tabellen abhängt

Ich habe eine Tabelle namens „Client“, die von Eingaben aus anderen Tabellen abhängt. Mit den folgenden Spezifikationen:

crewdb=#\d+ client;
                                                    Table "public.client"
       Column        |  Type   | Collation | Nullable |           Default            | Storage  | Stats target | Description
---------------------+---------+-----------+----------+------------------------------+----------+--------------+-------------
 clientid            | integer |           | not null | generated always as identity | plain    |              |
 account_name        | text    |           | not null |                              | extended |              |
 last_name           | text    |           |          |                              | extended |              |
 first_name          | text    |           |          |                              | extended |              |
 address             | text    |           | not null |                              | extended |              |
 suburbid            | integer |           |          |                              | plain    |              |
 cityid              | integer |           |          |                              | plain    |              |
 post_code           | integer |           | not null |                              | plain    |              |
 business_phone      | text    |           |          |                              | extended |              |
 home_phone          | text    |           |          |                              | extended |              |
 mobile_phone        | text    |           |          |                              | extended |              |
 alternative_phone   | text    |           |          |                              | extended |              |
 email               | text    |           |          |                              | extended |              |
 quote_detailsid     | integer |           |          |                              | plain    |              |
 invoice_typeid      | integer |           |          |                              | plain    |              |
 payment_typeid      | integer |           |          |                              | plain    |              |
 job_typeid          | integer |           |          |                              | plain    |              |
 communicationid     | integer |           |          |                              | plain    |              |
 accessid            | integer |           |          |                              | plain    |              |
 difficulty_levelid  | integer |           |          |                              | plain    |              |
 current_lawn_price  | numeric |           |          |                              | main     |              |
 square_meters       | numeric |           |          |                              | main     |              |
 note                | text    |           |          |                              | extended |              |
 client_statusid     | integer |           |          |                              | plain    |              |
 reason_for_statusid | integer |           |          |                              | plain    |              |
Indexes:
    "client_pkey" PRIMARY KEY, btree (clientid)
    "account_name_check" UNIQUE CONSTRAINT, btree (account_name)
Foreign-key constraints:
    "client_accessid_fkey" FOREIGN KEY (accessid) REFERENCES access(accessid)
    "client_cityid_fkey" FOREIGN KEY (cityid) REFERENCES city(cityid)
    "client_client_statusid_fkey" FOREIGN KEY (client_statusid) REFERENCES client_status(client_statusid)
    "client_communicationid_fkey" FOREIGN KEY (communicationid) REFERENCES communication(communicationid)
    "client_difficulty_levelid_fkey" FOREIGN KEY (difficulty_levelid) REFERENCES difficulty_level(difficulty_levelid)
    "client_invoice_typeid_fkey" FOREIGN KEY (invoice_typeid) REFERENCES invoice_type(invoice_typeid)
    "client_job_typeid_fkey" FOREIGN KEY (job_typeid) REFERENCES job_type(job_typeid)
    "client_payment_typeid_fkey" FOREIGN KEY (payment_typeid) REFERENCES payment_type(payment_typeid)
    "client_quote_detailsid_fkey" FOREIGN KEY (quote_detailsid) REFERENCES quote_details(quote_detailsid)
    "client_reason_for_statusid_fkey" FOREIGN KEY (reason_for_statusid) REFERENCES reason_for_status(reason_for_statusid)
    "client_suburbid_fkey" FOREIGN KEY (suburbid) REFERENCES suburb(suburbid)
Referenced by:
    TABLE "work" CONSTRAINT "work_clientid_fkey" FOREIGN KEY (clientid) REFERENCES client(clientid)

Die Spalte „Client-ID“ (Primärschlüssel) ist nicht in der richtigen Reihenfolge, da Clientdatensätze wie folgt gelöscht wurden:

crewdb=# select clientid from client order by clientid asc limit 22;
 clientid
----------
        2
        3
        4
        5
        6
        7
        8
        9
       10
       11
       12
       13
       14
       15
       17
       19
       21
       22
       23
       24
       26
       30
(22 rows)

zB wurden Zeile 1 und 25 gelöscht. Gibt es eine Möglichkeit, den Index von 1 Schritt für Schritt neu zu starten, wobei die Beziehungen zu anderen Tabellen berücksichtigt werden und das alles auf sichere Weise?

Antwort1

Haftungsausschluss: Im Prinzip gefällt mir die Idee, schöne und saubere IDs zu haben. Die Neunummerierung bringt jedoch keinen Vorteil, wenn sie erfolgreich ist, während sie die Datenbank zerstört, wenn sie fehlschlägt.

Zunächst sollten Sie sich vergewissern, dass Sie dereinziger Benutzer, der mit der Datenbank verbunden ist. Wir werden trotzdem Transaktionen verwenden, aber dadurch kann die Datenbank ihre Arbeit schneller erledigen.

Bevor Sie die clientTabelle neu nummerieren, müssen Sie die FOREIGN KEYEinschränkungen ändern, die auf die Tabelle verweisen:

Referenced by: TABLE "work" CONSTRAINT "work_clientid_fkey" FOREIGN KEY (clientid) REFERENCES client(clientid)

und füge die CASCADEAktion hinzu ON UPDATE(vgl.CREATE TABLE-Referenz):

BEGIN;
ALTER TABLE work DROP CONSTRAINT work_clientid_fkey;
ALTER TABLE work ADD CONSTRAINT work_clientid_fkey
    FOREIGN KEY (clientid) REFERENCES client ON UPDATE CASCADE;
COMMIT;

work.clientidDadurch wird die Spalte automatisch aktualisiert , wenn sich die client.clientidSpalte ändert. Wenn dies erledigt ist, können wir eine SELECTAnweisung verwenden, um die neuen IDs zu generieren und das Ergebnis verwenden, um eine UPDATEAnweisung auszugeben, wiein dieser Antwort erklärt. Sie können dies tun mit:

BEGIN;
CREATE SEQUENCE temp_client_id;
-- The real work begins
UPDATE client
SET clientid = ids.new_id
FROM (SELECT clientid AS old_id, nextval('temp_client_id') AS new_id
      FROM client ORDER BY clientid) AS ids
WHERE clientid = ids.old_id;
-- Clean up
DROP SEQUENCE temp_client_id;
COMMIT;

Nachdem dies alles erledigt ist, möchten Sie möglicherweise den Wert der Sequenz aktualisieren, die Sie zum Generieren von IDs für die clientTabelle verwenden (nennen wir sie client_id_seq):

SELECT setval('client_id_seq', MAX(clientid)) FROM client;

verwandte Informationen