memperbarui baris tabel di postgres menggunakan subquery

304

Menggunakan postgres 8.4, Tujuan saya adalah memperbarui tabel yang ada:

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
);

Awalnya saya menguji permintaan saya menggunakan pernyataan 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

menjadi Newbie Saya gagal mengonversi ke memperbarui pernyataan yaitu., memperbarui baris yang ada dengan nilai yang dikembalikan oleh pernyataan pilih. Setiap bantuan sangat dihargai.

stackover
sumber
apakah Anda memiliki id dalam tabel alamat, yang dapat digunakan untuk menentukan baris yang ada?
Andrey Adamovich
ya saya lakukan tetapi sistemnya dihasilkan.
stackover

Jawaban:

683

Postgres memungkinkan:

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;

Sintaks ini bukan SQL standar, tetapi jauh lebih nyaman untuk tipe kueri ini daripada SQL standar. Saya percaya Oracle (setidaknya) menerima sesuatu yang serupa.

Andrew Lazarus
sumber
tampaknya saya sedang mencoba untuk hal yang sedikit berbeda misalnya. jika ada 3 kolom bool c1, c2, c3 semuanya diatur ke false pada awalnya. tetapi berdasarkan subquery diatur ke true. perbarui set c1 = TRUE where id in (subquery1), set c2 = TRUE where id in (subquery2), set c3 = True where id in (subquery3). Saya berhasil ketika saya membagi ini sebagai 3 pembaruan tetapi saya tidak yakin bagaimana mencapai hasilnya dengan satu pembaruan. Semoga ini masuk akal.
stackover
3
FWIW, Oracle memang menerima konstruksi dasar itu, namun kinerja pembaruan cenderung menurun ketika tabel semakin besar. Tidak apa-apa karena Oracle juga mendukung pernyataan MERGE.
gsiems
3
Ini sama sekali tidak bekerja di postgresql 9.5, saya dapatERROR: 42P01: relation "dummy" does not exist
user9645
73
dummyharus diganti dengan nama tabel yang Anda coba perbarui. Harap mengerti pertanyaan dan jawaban sebelum mencoba mendaftar.
Andrew Lazarus
1
Mungkin layak untuk disebutkan bahwa di awal permintaan tidak perlu menentukan path ke kolom di sebelah kiri, hanya di akhir, jika tidak db akan mengeluh dengan ERROR: referensi kolom "address_id" ambigu
OJVM
126

Anda mengejar UPDATE FROMsintaks.

UPDATE 
  table T1  
SET 
  column1 = T2.column1 
FROM 
  table T2 
  INNER JOIN table T3 USING (column2) 
WHERE 
  T1.column2 = T2.column2;

Referensi

Brian Webster
sumber
2
Seharusnya jawaban yang dipilih
Joshua Kifer
51

Jika tidak ada keuntungan kinerja menggunakan gabungan, maka saya lebih suka Common Table Expressions (CTE) agar mudah dibaca:

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 sedikit lebih modern.

steevee
sumber
1
Sintaksnya tidak kompatibel dengan versi Postgres yang lebih lama, sebelum v9.1, (lihat postgresql.org/docs/9.1/static/sql-update.html dan versi sebelumnya) Saya menggunakan v8.2, jadi Anda harus untuk menempatkan seluruh pernyataan CTE / With di dalam tanda kurung setelah kata kunci DARI dan itu akan bekerja.
Spcogg yang kedua
9

Ada banyak cara untuk memperbarui baris.

Ketika datang ke UPDATEbaris menggunakan subqueries, Anda bisa menggunakan salah satu dari pendekatan ini.

  1. Approach-1 [Menggunakan referensi tabel langsung]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2>
WHERE
  <table1>.address_id=<table2>.address_i;

Penjelasan: table1adalah tabel yang ingin kita perbarui, table2 adalah tabel, dari mana kita akan mendapatkan nilai yang akan diganti / diperbarui. Kami menggunakan FROMklausa, untuk mengambil table2data. WHERE klausa akan membantu mengatur pemetaan data yang tepat.

  1. Approach-2 [Menggunakan SubQueries]
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;

Penjelasan: Di sini kita menggunakan subquerie di dalam FROMklausa, dan memberikan alias untuk itu. Sehingga akan bertindak seperti meja.

  1. Approach-3 [Menggunakan beberapa tabel yang Bergabung]
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;

Penjelasan: Kadang-kadang kita menghadapi situasi dalam tabel yang bergabung sangat penting untuk mendapatkan data yang tepat untuk pembaruan. Untuk melakukannya, Postgres memungkinkan kita untuk Bergabung dengan beberapa tabel di dalam FROMklausa.

  1. Approach-4 [Menggunakan DENGAN pernyataan]

    • 4.1 [Menggunakan kueri sederhana]
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 [Menggunakan kueri dengan BERGABUNG kompleks]
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;

Penjelasan: Dari Postgres 9.1, WITHkonsep ( ) ini telah diperkenalkan. Menggunakan itu, Kami dapat membuat pertanyaan kompleks dan menghasilkan hasil keinginan. Di sini kita menggunakan pendekatan ini untuk memperbarui tabel.

Saya harap, ini akan sangat membantu .😊

Mayur
sumber
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;
Pugazendhi Asaimuthu
sumber
1

@ Mayur "4.2 [Menggunakan kueri dengan kompleks BERGABUNG]" dengan Common Table Expressions (CTEs) membantu saya.

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;

Semoga ini bisa membantu ...: D

Festus Ngor
sumber