Postgresql 10: cómo volver a secuenciar una columna de clave principal en una tabla que depende de otras tablas

Postgresql 10: cómo volver a secuenciar una columna de clave principal en una tabla que depende de otras tablas

Tengo una tabla llamada cliente que depende de la entrada de otras tablas. con las siguientes especificaciones:

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)

La columna clientid (clave principal) está desordenada ya que los registros de clientes se eliminaron de la siguiente manera:

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)

por ejemplo, se eliminaron las filas 1 y 25. ¿Hay alguna manera de reiniciar el índice desde 1 incremento en 1 teniendo en cuenta las relaciones con otras tablas y haciendo todo eso de manera segura?

Respuesta1

Descargo de responsabilidad: En principio, me gusta la idea de tener identificadores bonitos y limpios. Sin embargo, renumerarlos no ofrece ninguna ventaja si tiene éxito, mientras que dañará la base de datos si falla.

Primero es mejor asegurarse usted mismo, que usted es elúnico usuario conectado a la base de datos. Usaremos transacciones de todos modos, pero eso ayudará a que la base de datos haga su trabajo más rápido.

Antes de volver a numerar la clienttabla, debe cambiar las FOREIGN KEYrestricciones que hacen referencia a la tabla:

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

y añadir la CASCADEacción a ON UPDATE(cf.CREAR TABLA de referencia):

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;

Esto actualizará automáticamente la work.clientidcolumna cuando ésta client.clientidcambie. Cuando se hace esto, podemos usar una SELECTdeclaración para generar los nuevos identificadores y usar el resultado para emitir una UPDATEdeclaración, comoexplicado en esta respuesta. Puedes hacerlo con:

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;

Una vez hecho todo esto, es posible que desees actualizar el valor de la secuencia que estás utilizando para generar identificadores para la clienttabla (llamémosla client_id_seq):

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

información relacionada