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

Chèn dữ liệu và đặt khóa ngoại với Postgres

Bảng users phải có một số khóa chính mà bạn đã không tiết lộ. Với mục đích của câu trả lời này, tôi sẽ đặt tên cho nó là users_id .

Bạn có thể giải quyết vấn đề này khá dễ dàng với CTE sửa đổi dữ liệu được giới thiệu với PostgreSQL 9.1 :

country là duy nhất

Toàn bộ hoạt động khá đơn giản trong trường hợp này:

WITH i AS (
    INSERT INTO addresses (country) 
    SELECT country
    FROM   users
    WHERE  address_id IS NULL 
    RETURNING id, country
    )
UPDATE users u
SET    address_id = i.id
FROM   i
WHERE  i.country = u.country;

Bạn đề cập đến phiên bản 8.3 trong câu hỏi của bạn. Nâng cấp! Postgres 8.3 đã hết tuổi thọ.

Có thể là như vậy, điều này đủ đơn giản với phiên bản 8.3. Bạn chỉ cần hai câu lệnh:

INSERT INTO addresses (country) 
SELECT country
FROM   users
WHERE  address_id IS NULL;

UPDATE users u
SET    address_id = a.id
FROM   addresses a
WHERE  address_id IS NULL 
AND    a.country = u.country;

country không phải là duy nhất

Đó là thách thức hơn. Bạn có thể chỉ cần tạo một địa chỉ và liên kết đến địa chỉ đó nhiều lần. Nhưng bạn đã đề cập đến mối quan hệ 1:1 loại trừ một giải pháp thuận tiện như vậy.

WITH s AS (
    SELECT users_id, country
         , row_number() OVER (PARTITION BY country) AS rn
    FROM   users
    WHERE  address_id IS NULL 
    )
    , i AS (
    INSERT INTO addresses (country) 
    SELECT country
    FROM   s
    RETURNING id, country
    )
    , r AS (
    SELECT *
         , row_number() OVER (PARTITION BY country) AS rn
    FROM   i
    )
UPDATE users u
SET    address_id = r.id
FROM   r
JOIN   s USING (country, rn)    -- select exactly one id for every user
WHERE  u.users_id = s.users_id
AND    u.address_id IS NULL;

Vì không có cách nào để chỉ định rõ ràng chính xác một id được trả về từ INSERT cho mọi người dùng trong một tập hợp có country giống hệt nhau , Tôi sử dụng hàm cửa sổ row_number() để làm cho chúng trở nên độc đáo.

Không thẳng tiến với Postgres 8.3 . Một cách khả thi:

INSERT INTO addresses (country) 
SELECT DISTINCT country -- pick just one per set of dupes
FROM   users
WHERE  address_id IS NULL;

UPDATE users u
SET    address_id = a.id
FROM   addresses a
WHERE  a.country = u.country
AND    u.address_id IS NULL
AND NOT EXISTS (
    SELECT * FROM addresses b
    WHERE  b.country = a.country
    AND    b.users_id < a.users_id
    ); -- effectively picking the smallest users_id per set of dupes

Lặp lại điều này cho đến NULL cuối cùng giá trị bị biến mất khỏi users.address_id .




  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ánh xe xây dựng không thành công cho psycopg2 - MacOSX sử dụng virtualenv và pip

  2. CHÈN VÀO ... TỪ CHỌN ... QUAY LẠI ánh xạ id

  3. Cách Atan2 () hoạt động trong PostgreSQL

  4. CHÈN các hàng vào nhiều bảng trong một truy vấn, chọn từ một bảng có liên quan

  5. Thiết kế cơ sở dữ liệu tạm thời, có sự thay đổi (hàng trực tiếp so với hàng nháp)