2012-08-28 19 views
6

Tôi có một nhiều-nhiều giữa foobar mô hình hóa như một bảng foo_bar với foo_idbar_id.Chuyển đổi một mối quan hệ nhiều-nhiều đến một-nhiều trong PostgreSQL

Tôi muốn mô hình hóa mô hình này dưới dạng một đến nhiều (dữ liệu của tôi cho phép).

Tôi đã thêm một cột foo_id vào bar nhưng bây giờ tôi muốn di chuyển dữ liệu của mình. Vì vậy, tôi muốn

UPDATE bar SET foo_id = f where id = b; 

nơi mỗi cặp fb đang đến từ

SELECT foo_id AS f, bar_id AS b FROM foo_bar; 

Có thể làm điều này trong SQL (và đặc biệt là PostgreSQL 9.0)?

Tôi biết cách thực hiện các lựa chọn con trong các CẬP NHẬT khi chỉ có một giá trị, nhưng bị chặn làm cách nào để thực hiện trong trường hợp này.

Trả lời

5
UPDATE bar b 
SET foo_id = fb.foo_id 
FROM foo_bar fb 
WHERE fb.bar_id = b.bar_id; 

Nếu bạn nên có nhiều hàng cho một bar (mà bạn không nên, theo mô tả của bạn) một trong những hàng sẽ được cập nhật nhiều lần và kết quả là tùy ý.

Biểu mẫu truy vấn này thường hoạt động tốt hơn so với truy vấn con tương quan.

Lưu ý rằng khóa chính của bar thực sự nên được đặt tên là bar_id - Tôi sử dụng tên đó trong truy vấn.

+0

nên kéo dòng được fb.bar_id = b.id? –

+0

@JamesTauber: Không. Không nên có một 'id' trong mô hình. Sử dụng tên cột không mô tả 'id' là một mẫu chống. Khóa chính nên được đặt tên là 'bar_id'. –

+0

đủ công bằng, chỉ cần ánh xạ nó đến các chi tiết cụ thể trong câu hỏi của tôi –

2

Nếu bạn thực sự có mối quan hệ 1-nhiều, thì bạn không cần quan tâm đến giá trị của foo bạn thực hiện cho một thanh nhất định - chỉ có một hoặc tất cả đều giống nhau.

Bạn có thể làm như sau:

update bar 
    set foo_id = (select max(foo_id) from foo_bar where foo_bar.bar_id = bar.id) 

Các subquery giới hạn kết quả đến một giá trị duy nhất.

3

Bạn vẫn có thể tham gia bảng trong UPDATE báo cáo, hãy thử

UPDATE bar a 
SET  foo_id = c.foo_id 
FROM (
      SELECT foo_id, bar_id 
      FROM foo_bar 
     ) c 
WHERE a.id = c.bar_id 

hoặc đơn giản là

UPDATE bar a 
SET  foo_id = c.foo_id 
FROM foo_bar c 
WHERE a.id = c.bar_id 
+0

'SET' không chấp nhận tên cột đủ điều kiện. –

+0

@ErwinBrandstetter thực sự điều này không được kiểm tra. không postgre đủ nghiêm ngặt? hehe, vì vậy trong trường hợp này tôi nên viết lại nó thành 'SET foo_id = c.foo_id'?" –

+0

Chính xác: 'SET foo_id = c.foo_id', như trong câu trả lời của tôi. Tôi trích dẫn hướng dẫn [ở đây] (http: // www.postgresql.org/docs/current/interactive/sql-update.html): 'Không bao gồm tên của bảng trong đặc tả của cột mục tiêu - ví dụ: tab CẬP NHẬT SET tab.col = 1 không hợp lệ.' –