2012-10-15 32 views
6

Giả sử tôi có hai bảng: CustomerCity. Có rất nhiều Customer s sống trong cùng một City. Các thành phố có uid là khóa chính. Khách hàng có một khóa tham chiếu nước ngoài đến thành phố của họ thông qua Customer.city_uid.Làm cách nào để thay đổi giá trị của khóa ngoài trong postgresql?

Tôi phải hoán đổi hai số City.uid với nhau vì lý do bên ngoài. Nhưng khách hàng nên gắn bó với thành phố của họ. Do đó, cần phải hoán đổi Customer.city_uid giây. Vì vậy, tôi nghĩ rằng tôi lần đầu tiên trao đổi các City.uid s và sau đó thay đổi Customer.city_uid s theo thông qua một UPDATE -statement. Thật không may, tôi không thể làm điều đó vì những uids này được tham chiếu từ Customer-có thể sử dụng được và PostgreSQL ngăn tôi làm điều đó.

Có cách nào dễ dàng để hoán đổi hai số City.uid s với nhau cũng như Customer.city_uid s không?

+0

Vấn đề trở nên lớn hơn nếu bạn có N bảng tham chiếu bảng "chính" (trong trường hợp thành phố) của bạn. Cho đến nay, đây là giải pháp yêu thích của tôi: http://stackoverflow.com/a/18273069/633961 (Nhưng tôi vẫn đang tìm cách tốt hơn để giải quyết vấn đề này). – guettli

Trả lời

1

Bản năng của tôi là khuyên bạn không nên cố gắng thay đổi trường id của bảng city. Nhưng có rất nhiều thông tin còn thiếu ở đây. Vì vậy, nó thực sự là một cảm giác chứ không phải là góc nhìn dứt khoát.

Thay vào đó, tôi sẽ hoán đổi các giá trị trong các trường khác khác của bảng city. Ví dụ: thay đổi tên thành phố1 thành tên thành phố2 và ngược lại.

Ví dụ:

OLD TABLE        NEW TABLE 

id | name | population     id | name | population 
-------------------------    ------------------------- 
    1 | ABerg | 123456      1 | BBerg | 654321 
    2 | BBerg | 654321      2 | ABerg | 123456 
    3 | CBerg | 333333      3 | CBerg | 333333 

(ID không được xúc động, nhưng các giá trị khác đã được hoán đổi mặt chức năng giống như trao đổi các ID, nhưng với 'cảm ứng nhẹ nhàng hơn' truy vấn mà không cần phải. thực hiện bất kỳ thay đổi chế về bảng vv)


Sau đó, trong các bảng liên quan của bạn, bạn có thể làm ...

UPDATE 
    Customer 
SET 
    city_uid = CASE WHEN city_uid = 1 THEN 2 ELSE 1 END 
WHERE 
    city_uid IN (1,2) 

Nhưng sau đó, bạn có các bảng khác tham chiếu city_uid không? Và nếu có, bạn có thể lặp lại bản cập nhật đó trên tất cả các bảng đó hay không?

+0

Cảm ơn bạn, tuy nhiên, điều đó là không thể. Tôi thực sự cần phải thay đổi uids. – AME

+0

Bạn có thể giải thích thêm không? Nếu 'uid = 1' bây giờ được liên kết với tên thành phố, v.v. của những gì' uid = 2' đã từng có, thì bạn chưa làm điều tương tự? Ở khía cạnh nào thì điều này có thể ngắn gọn? Chỉ để chúng tôi có thể đề xuất các giải pháp thay thế. – MatBailie

+0

Thêm một ví dụ trực quan cho thấy trao đổi tên, v.v., có chức năng giống như hoán đổi trường ID. – MatBailie

4

Một giải pháp có thể là:

BEGIN; 
1. Drop foreign key 
2. Make update 
3. Create foreign key 
COMMIT; 

Hoặc:

BEGIN; 
1. Insert "new" correct information 
2. Remove outdated information 
COMMIT; 
1

Bạn có thể tạo ra hai thành phố tạm thời.

Bạn sẽ có:

  • phố 1
  • City 2
  • Thành phố Temp 1
  • Thành phố Temp 2

Sau đó, bạn có thể làm tiếp theo:

  1. Cập nhật tất cả các UID khách hàng từ thành phố 1 đến thành phố Temp 1.
  2. Cập nhật tất cả các UID khách hàng từ thành phố 2 đến Thành phố Temp 2.
  3. Swap phố 1 và 2 UID
  4. Move tất cả các khách hàng trở lại từ Thành phố Temp 1 đến Thành phố 1.
  5. Di chuyển tất cả Khách hàng quay lại từ Thành phố Temp 2 đến Thành phố 2.
  6. Xóa các thành phố tạm thời.
Các vấn đề liên quan