aggiornamento delle righe della tabella in postgres usando subquery


304

Utilizzando Postgres 8.4, il mio obiettivo è aggiornare la tabella esistente:

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

Inizialmente ho testato la mia query utilizzando l'istruzione 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

essendo Newbie non riesco a convertire l'istruzione update, ad esempio l'aggiornamento delle righe esistenti con i valori restituiti dall'istruzione select. Qualsiasi aiuto è molto apprezzato.


hai qualche tipo di ID nella tabella degli indirizzi, che può essere usato per determinare che la riga esiste?
Andrey Adamovich,

sì, ma il suo sistema è stato generato.
StackOver

Risposte:


683

Postgres consente:

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;

Questa sintassi non è SQL standard, ma è molto più conveniente per questo tipo di query rispetto a SQL standard. Credo che Oracle (almeno) accetti qualcosa di simile.


sembra che sto provando qualcosa di diverso per es. se ci sono 3 colonne bool c1, c2, c3 tutte inizialmente impostate su false. ma in base alla subquery sono impostati su true. update set c1 = TRUE dove id in (subquery1), imposta c2 = TRUE dove id in (subquery2), imposta c3 = True dove id in (subquery3). Ho avuto successo quando ho diviso questo come 3 aggiornamenti, ma non sono sicuro di come ottenere il risultato con un singolo aggiornamento. spero che questo abbia senso.
StackOver

3
FWIW, Oracle accetta questo costrutto di base, tuttavia le prestazioni dell'aggiornamento tendono a peggiorare notevolmente man mano che le tabelle diventano più grandi. Va bene anche se Oracle supporta anche l'istruzione MERGE.
gsiems

3
Questo non funziona in Postgresql 9.5, ottengoERROR: 42P01: relation "dummy" does not exist
user9645,

73
dummydeve essere sostituito dal nome della tabella che si sta tentando di aggiornare. Si prega di comprendere la domanda e la risposta prima di provare ad applicare.
Andrew Lazarus,

1
Vale la pena ricordare che all'inizio della query non è necessario specificare il percorso della colonna del lato sinistro, solo alla fine, altrimenti il ​​db si lamenterà con ERRORE: il riferimento alla colonna "address_id" è ambiguo
OJVM,


51

Se non ci sono miglioramenti delle prestazioni utilizzando un join, preferisco le espressioni di tabella comuni (CTE) per la leggibilità:

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 un po 'più moderno.


1
La sintassi non è compatibile con le versioni precedenti di Postgres, prima della v9.1, (vedi postgresql.org/docs/9.1/static/sql-update.html e le versioni precedenti) Sono su v8.2, quindi hai per inserire l'intera istruzione CTE / With tra parentesi dopo la parola chiave FROM e funzionerà.
Spcogg il secondo

9

Esistono molti modi per aggiornare le righe.

Quando si tratta di UPDATErighe utilizzando le sottoquery, è possibile utilizzare uno di questi approcci.

  1. Approccio-1 [Uso del riferimento diretto alla tabella]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2>
WHERE
  <table1>.address_id=<table2>.address_i;

Spiegazione: table1è la tabella che vogliamo aggiornare, table2 è la tabella, dalla quale otterremo il valore da sostituire / aggiornare. Stiamo usando la FROMclausola per recuperare table2i dati. WHERE la clausola aiuterà a impostare la corretta mappatura dei dati.

  1. Approccio-2 [Utilizzo di subquisiti]
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;

Spiegazione: Qui stiamo usando subquerie all'interno della FROMclausola e diamo un alias ad essa. In modo che agirà come il tavolo.

  1. Approach-3 [Uso di più tabelle unite]
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;

Spiegazione: A volte affrontiamo la situazione in quel join tabella è così importante per ottenere dati adeguati per l'aggiornamento. Per fare ciò, Postgres ci consente di unire più tabelle all'interno della FROMclausola.

  1. Approach-4 [Uso dell'istruzione WITH]

    • 4.1 [Uso della query semplice]
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 [Utilizzo di query con JOIN complessi]
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;

Spiegazione: Da Postgres 9.1, questo WITHconcetto ( ) è stato introdotto. Usando questo possiamo fare qualsiasi domanda complessa e generare il risultato desiderato. Qui stiamo usando questo approccio per aggiornare la tabella.

Spero che ciò possa essere utile


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 [Utilizzo di query con JOIN complessi]" con Common Table Expressions (CTE) ha fatto il trucco per me.

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;

Spero che questo aiuti ...: D

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.