PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Thu gọn hoặc đánh số lại ID cho tất cả các bảng và đặt lại trình tự thành max (id)?

Câu hỏi cũ, nhưng chúng tôi nhận được một câu hỏi mới từ một người dùng tuyệt vọng trên dba.SE sau khi cố gắng áp dụng những gì được đề xuất ở đây. Tìm câu trả lời với thêm chi tiết và giải thích ở đó :

câu trả lời hiện được chấp nhận sẽ không thành công trong hầu hết các trường hợp .

  • Thông thường, bạn có PRIMARY KEY hoặc UNIQUE ràng buộc trên một id cột NOT DEFERRABLE theo mặc định. (OP đề cập đến references and constraints .) Những ràng buộc như vậy được kiểm tra sau mỗi hàng, vì vậy bạn rất có thể gặp vi phạm duy nhất lỗi khi cố gắng. Chi tiết:

  • Thông thường, một người muốn giữ lại thứ tự hàng ban đầu đồng thời thu hẹp khoảng cách. Nhưng thứ tự các hàng được cập nhật là tùy ý , dẫn đến số lượng tùy ý. Ví dụ được minh họa dường như vẫn giữ nguyên trình tự ban đầu vì bộ nhớ vật lý vẫn trùng với thứ tự mong muốn (các hàng được chèn theo thứ tự mong muốn chỉ một lúc trước đó), điều này hầu như không bao giờ xảy ra trong các ứng dụng trong thế giới thực và hoàn toàn không đáng tin cậy.

Vấn đề phức tạp hơn tưởng tượng lúc đầu. Một giải pháp (trong số những giải pháp khác) nếu bạn có đủ khả năng để tạm thời loại bỏ ràng buộc PK / UNIQUE (và các ràng buộc FK liên quan):

BEGIN;

LOCK tbl;

-- remove all FK constraints to the column

ALTER TABLE tbl DROP CONSTRAINT tbl_pkey;  -- remove PK

-- for the simple case without FK references - or see below:    
UPDATE tbl t  -- intermediate unique violations are ignored now
SET    id = t1.new_id
FROM  (SELECT id, row_number() OVER (ORDER BY id) AS new_id FROM tbl) t1
WHERE  t.id = t1.id;

-- Update referencing value in FK columns at the same time (if any)

SELECT setval('tbl_id_seq', max(id)) FROM tbl;  -- reset sequence

ALTER TABLE tbl ADD CONSTRAINT tbl_pkey PRIMARY KEY(id); -- add PK back

-- add all FK constraints to the column back

COMMIT;

Điều này cũng nhiều nhanh hơn đối với các bảng lớn, bởi vì việc kiểm tra (các) ràng buộc PK (và FK) cho mọi hàng tốn kém hơn rất nhiều so với việc loại bỏ (các) ràng buộc và thêm lại (chúng).

Nếu có các cột FK trong các bảng khác tham chiếu đến tbl.id , sử dụng CTE sửa đổi dữ liệu để cập nhật tất cả chúng.

Ví dụ cho bảng fk_tbl và một cột FK fk_id :

WITH u1 AS (
   UPDATE tbl t
   SET    id = t1.new_id
   FROM  (SELECT id, row_number() OVER (ORDER BY id) AS new_id FROM tbl) t1
   WHERE  t.id = t1.id
   RETURNING t.id, t1.new_id  -- return old and new ID
   )
UPDATE fk_tbl f
SET    fk_id = u1.new_id      -- set to new ID
FROM   u1
WHERE  f.fk_id = u1.id;       -- match on old ID

Xem thêm trong câu trả lời được tham khảo trên dba.SE .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. bế tắc trong postgres về truy vấn cập nhật đơn giản

  2. Làm cách nào để CẬP NHẬT một cột trong một bảng PostgreSQL lớn bằng Python / psycopg2 một cách hiệu quả?

  3. chỉ mục dataframe.to_sql làm khóa chính trong postgresql

  4. Rails + Postgres:Không trả lại thông tin múi giờ trên cột từ bảng đã tham gia

  5. Làm thế nào để lấy tên của một tài liệu trong Alfresco với SQL?