alt sorgu kullanarak postgres tablo satırlarını güncelleme


304

Postgres 8.4 kullanarak Amacım mevcut tabloyu güncellemek:

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

Başlangıçta eklemek deyimi kullanarak benim sorgu test:

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

Newbie olmak ben güncelleme deyimi yani, mevcut ifade select deyimi tarafından döndürülen değerleri ile güncelleme dönüştürme başarısız. Herhangi bir yardım çok takdir edilmektedir.


Adres tablosunda, satırın var olduğunu belirlemek için kullanılabilecek herhangi bir kimlik var mı?
Andrey Adamovich

evet yapıyorum ama onun sys üretti.
stackover

Yanıtlar:


683

Postgres şunları sağlar:

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;

Bu sözdizimi standart SQL değildir, ancak bu sorgu türü için standart SQL'den çok daha kullanışlıdır. Oracle'ın (en azından) benzer bir şeyi kabul ettiğine inanıyorum.


Görünüşe göre örneğin biraz farklı bir şey deniyorum. başlangıçta false değerine ayarlanmış 3 bool c1, c2, c3 sütunu varsa. ancak alt sorguyu temel alan true olarak ayarlanır. güncelleme seti c1 = DOĞRU olduğunda id (alt sorgu1), set c2 = DOĞRU burada id (alt sorgu2), set c3 = Doğru nerede id (alt sorgu3). Bunu 3 güncelleme olarak böldüğümde başarılı oldum, ancak tek bir güncelleme ile sonuca nasıl ulaşacağımdan emin değilim. umarım bu mantıklıdır.
stackover

3
FWIW, Oracle bu temel yapıyı kabul ediyor, ancak güncellemelerin performansı tablolar büyüdükçe ciddi şekilde düşme eğilimi gösteriyor. Oracle MERGE deyimini de desteklediği için sorun değil.
gsiems

3
Bu tamamen postgresql 9.5 çalışmıyor, benERROR: 42P01: relation "dummy" does not exist
user9645

73
dummygüncellenmeye çalıştığınız tablonun adıyla değiştirilmelidir. Başvurmaya çalışmadan önce lütfen soru ve cevabı anlayın.
Andrew Lazarus

1
Sorgunun başlangıcında, sol taraftaki sütunun yolunu belirtmek gerekli değildir, sadece sonunda, aksi takdirde db ERROR ile şikayet edecektir: sütun başvurusu "adres_kimliği" belirsiz
OJVM


51

Birleştirme kullanarak performans artışı yoksa, okunabilirlik için Ortak Tablo İfadelerini (CTE'ler) tercih ederim:

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 biraz daha modern.


1
Sözdizimi v9.1'den önceki Postgres'in eski sürümleriyle uyumlu değildir (bkz. Postgresql.org/docs/9.1/static/sql-update.html ve önceki sürümler) v8.2'deyim. CTE / With ifadesinin tamamını FROM anahtar sözcüğünden sonra köşeli parantez içine koymak ve çalışacaktır.
İkinci

10

Satırları güncellemenin birçok yolu vardır.

UPDATEAlt sorguları kullanan satırlar söz konusu olduğunda , bu yaklaşımlardan herhangi birini kullanabilirsiniz.

  1. Yaklaşım-1 [Doğrudan tablo referansını kullanma]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2>
WHERE
  <table1>.address_id=<table2>.address_i;

Açıklama: table1güncellemek istediğimiz table2 tablo, değiştirilecek / güncellenecek değeri alacağımız tablodur. Verilerini FROMalmak için fıkra kullanıyoruz table2. WHERE fıkra, doğru veri eşlemesinin ayarlanmasına yardımcı olacaktır.

  1. Yaklaşım-2 [Alt Sorguları Kullanma]
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;

Açıklama: Burada FROMmaddede alt sorgu kullanıyoruz ve buna bir takma ad veriyoruz. Böylece masa gibi davranacak.

  1. Yaklaşım-3 [Birden Fazla Birleştirilmiş tablo kullanma]
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;

Açıklama: Bazen güncellemeyle ilgili doğru verileri elde etmek için bu masa birleşimindeki durumla karşı karşıyayız. Bunu yapmak için, Postgres FROMyan tümcede birden çok tabloya katılmamızı sağlar .

  1. Yaklaşım-4 [WITH ifadesi kullanılarak]

    • 4.1 [Basit sorgu kullanma]
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 [Sorguyu karmaşık JOIN ile kullanma]
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;

Açıklama: Postgres 9.1'den bu ( WITH) kavram tanıtıldı. Bunu kullanma Herhangi bir karmaşık sorgu yapabilir ve arzu sonucu üretebiliriz. Burada tabloyu güncellemek için bu yaklaşımı kullanıyoruz.

Umarım bu yardımcı olur.


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 [kompleks ile kullanma sorgu JOIN]" ile ortak tablo ifadeleri (CTEs) benim için hile yaptı.

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;

Umarım bu yardımcı olur ...: D

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.