cập nhật các hàng của bảng trong postgres bằng cách sử dụng truy vấn con


304

Sử dụng postgres 8.4, mục tiêu của tôi là cập nhật bảng hiện có:

CREATE TABLE public.dummy
(
  address_id SERIAL,
  addr1 character(40),
  addr2 character(40),
  city character(25),
  state character(2),
  zip character(5),
  customer boolean,
  supplier boolean,
  partner boolean

)
WITH (
  OIDS=FALSE
);

Ban đầu tôi đã kiểm tra truy vấn của mình bằng cách sử dụng câu lệnh insert:

insert into address customer,supplier,partner
SELECT  
    case when cust.addr1 is not null then TRUE else FALSE end customer, 
    case when suppl.addr1 is not null then TRUE else FALSE end supplier,
    case when partn.addr1 is not null then TRUE else FALSE end partner
from (
    SELECT *
        from address) pa
    left outer join cust_original cust
        on (pa.addr1=cust.addr1 and pa.addr2=cust.addr2 and pa.city=cust.city 
            and pa.state=cust.state and substring(cust.zip,1,5) = pa.zip  )
    left outer join supp_original suppl 
        on (pa.addr1=suppl.addr1 and pa.addr2=suppl.addr2 and pa.city=suppl.city 
                and pa.state=suppl.state and pa.zip = substring(suppl.zip,1,5))
    left outer join partner_original partn
        on (pa.addr1=partn.addr1 and pa.addr2=partn.addr2 and pa.city=partn.city
                  and pa.state=partn.state and pa.zip = substring(partn.zip,1,5) )
where pa.address_id = address_id

là Newbie Tôi không chuyển đổi sang cập nhật câu lệnh, tức là, cập nhật các hàng hiện có với các giá trị được trả về bởi câu lệnh chọn. Bất kỳ sự trợ giúp nào cũng được đánh giá cao.


Bạn có bất kỳ loại id nào trong bảng địa chỉ, có thể được sử dụng để xác định hàng đó đang tồn tại không?
Andrey Adamovich

vâng tôi làm nhưng hệ thống của nó tạo ra.
stackover

Câu trả lời:


683

Postgres cho phép:

UPDATE dummy
SET customer=subquery.customer,
    address=subquery.address,
    partn=subquery.partn
FROM (SELECT address_id, customer, address, partn
      FROM  /* big hairy SQL */ ...) AS subquery
WHERE dummy.address_id=subquery.address_id;

Cú pháp này không phải là SQL chuẩn, nhưng nó thuận tiện hơn nhiều cho loại truy vấn này so với SQL chuẩn. Tôi tin rằng Oracle (ít nhất) chấp nhận một cái gì đó tương tự.


có vẻ như tôi đang cố gắng cho một chút khác biệt ví dụ. nếu có 3 cột bool c1, c2, c3 đều được đặt thành false ban đầu. nhưng dựa trên truy vấn con được đặt thành đúng. Cập nhật bộ c1 = TRUE trong đó id trong (subquery1), đặt c2 = TRUE trong đó id trong (subquery2), đặt c3 = True trong đó id trong (subquery3). Tôi đã thành công khi chia thành 3 bản cập nhật nhưng tôi không chắc làm thế nào để đạt được kết quả chỉ với một bản cập nhật. hy vọng điều này có ý nghĩa.
stackover

3
FWIW, Oracle không chấp nhận cấu trúc cơ bản đó, tuy nhiên hiệu năng của bản cập nhật có xu hướng giảm nghiêm trọng khi các bảng ngày càng lớn hơn. Mặc dù vậy cũng tốt vì Oracle cũng hỗ trợ tuyên bố MERGE.
gsiems 11/03/2015

3
Điều này hoàn toàn không hoạt động trong postgresql 9.5, tôi nhận đượcERROR: 42P01: relation "dummy" does not exist
user9645

73
dummyphải được thay thế bằng tên của bảng bạn đang cố cập nhật. Hãy hiểu câu hỏi và trả lời trước khi thử áp dụng.
Andrew Lazarus

1
Có thể đáng để đề cập rằng khi bắt đầu truy vấn, không cần thiết phải chỉ định đường dẫn đến cột bên trái, chỉ ở cuối, nếu không, db sẽ khiếu nại với ERROR: tham chiếu cột "address_id" không rõ ràng
OJVM


51

Nếu không có hiệu suất tăng khi sử dụng phép nối, thì tôi thích Biểu thức bảng chung (CTE) để dễ đọc:

WITH subquery AS (
    SELECT address_id, customer, address, partn
    FROM  /* big hairy SQL */ ...
)
UPDATE dummy
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE dummy.address_id = subquery.address_id;

IMHO hiện đại hơn một chút.


1
Cú pháp không tương thích với các phiên bản cũ hơn của Postgres, trước v9.1, (xem postgresql.org/docs/9.1/static/sql-update.html và các phiên bản trước) Tôi có trên v8.2, vì vậy bạn có để đặt toàn bộ câu lệnh CTE / With bên trong ngoặc sau từ khóa TỪ và nó sẽ hoạt động.
Spcogg thứ hai

9

Có nhiều cách để cập nhật các hàng.

Khi nói đến UPDATEcác hàng bằng cách sử dụng các truy vấn con, bạn có thể sử dụng bất kỳ phương pháp nào trong số các phương pháp này.

  1. Cách tiếp cận-1 [Sử dụng tham chiếu bảng trực tiếp]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2>
WHERE
  <table1>.address_id=<table2>.address_i;

Giải thích: table1là bảng mà chúng tôi muốn cập nhật, table2 là bảng, từ đó chúng tôi sẽ nhận được giá trị được thay thế / cập nhật. Chúng tôi đang sử dụng FROMmệnh đề, để lấy table2dữ liệu của. WHERE mệnh đề sẽ giúp thiết lập ánh xạ dữ liệu thích hợp.

  1. Cách tiếp cận-2 [Sử dụng các câu hỏi con]
UPDATE
  <table1>
SET
  customer=subquery.customer,
  address=subquery.address,
  partn=subquery.partn
FROM
  (
    SELECT
      address_id, customer, address, partn
    FROM  /* big hairy SQL */ ...
  ) AS subquery
WHERE
  dummy.address_id=subquery.address_id;

Giải thích: Ở đây chúng tôi đang sử dụng subquerie bên trong FROMmệnh đề và đưa ra một bí danh cho nó. Vì vậy, nó sẽ hoạt động như bảng.

  1. Cách tiếp cận-3 [Sử dụng nhiều bảng đã tham gia]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2> as t2
  JOIN <table3> as t3
  ON
    t2.id = t3.id
WHERE
  <table1>.address_id=<table2>.address_i;

Giải thích: Đôi khi chúng tôi phải đối mặt với tình huống tham gia bảng đó rất quan trọng để có được dữ liệu phù hợp cho bản cập nhật. Để làm như vậy, Postgres cho phép chúng ta Tham gia nhiều bảng bên trong FROMmệnh đề.

  1. Cách tiếp cận-4 [Sử dụng câu lệnh VỚI]

    • 4.1 [Sử dụng truy vấn đơn giản]
WITH subquery AS (
    SELECT
      address_id,
      customer,
      address,
      partn
    FROM
      <table1>;
)
UPDATE <table-X>
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE <table-X>.address_id = subquery.address_id;
  • 4.2 [Sử dụng truy vấn với THAM GIA phức tạp]
WITH subquery AS (
    SELECT address_id, customer, address, partn
    FROM
      <table1> as t1
    JOIN
      <table2> as t2
    ON
      t1.id = t2.id;
    -- You can build as COMPLEX as this query as per your need.
)
UPDATE <table-X>
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE <table-X>.address_id = subquery.address_id;

Giải thích: Từ Postgres 9.1, WITHkhái niệm ( ) này đã được giới thiệu. Sử dụng điều đó Chúng tôi có thể thực hiện bất kỳ truy vấn phức tạp và tạo ra kết quả mong muốn. Ở đây chúng tôi đang sử dụng phương pháp này để cập nhật bảng.

Tôi hy vọng, điều này sẽ hữu ích .😊


1
update json_source_tabcol as d
set isnullable = a.is_Nullable
from information_schema.columns as a 
where a.table_name =d.table_name 
and a.table_schema = d.table_schema 
and a.column_name = d.column_name;

1

@Mayur "4.2 [Sử dụng truy vấn với THAM GIA phức tạp]" với Biểu thức bảng chung (CTE) đã giúp tôi.

WITH cte AS (
SELECT e.id, e.postcode
FROM employees e
LEFT JOIN locations lc ON lc.postcode=cte.postcode
WHERE e.id=1
)
UPDATE employee_location SET lat=lc.lat, longitude=lc.longi
FROM cte
WHERE employee_location.id=cte.id;

Hy vọng điều này sẽ giúp ...: D

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.