2013-01-24 12 views
9

Sono nuovo in PostgreSQL e sto provando a convertire una query da SQL Server.Aggiornamento postgres da sinistra join

Ho una tabella Utenti con, tra le altre, le colonne bUsrActive, bUsrAdmin e sUsrClientCode. Voglio aggiornare gli utenti e impostare bUsrActive = false se non esiste un altro utente con lo stesso sUsrClientCode dove bUsrAdmin = true e bUsrActive = true.

In SQL Server ho questa query

UPDATE u SET u.bUsrActive = 0 
FROM Users u 
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1 
WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL 

Sto cercando di convertire questo in Postgres. Ho scritto 3 approcci.

1) Il mio primo tentativo. Ovviamente non funziona.

UPDATE Users u 
    SET bUsrActive = false 
FROM Users u2 
WHERE u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = true AND u2.bUsrActive = true 
AND u.bUsrAdmin = false AND u.bUsrActive = true AND u2.nkUsr IS NULL; 

2) Capisco perché non funziona (aggiorna tutti gli utenti). Non riesco proprio a capire come posso fare riferimento agli utenti della tabella u nella parte UPDATE ... SET.

UPDATE Users 
    SET bUsrActive = false 
FROM Users u 
LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = true AND u2.bUsrActive = true 
WHERE u.bUsrAdmin = false AND u.bUsrActive = true AND u2.nkUsr IS NULL; 

3) Di seguito è funzionante, ma non utilizzando aderire.

UPDATE Users 
    SET bUsrActive = false 
WHERE NOT EXISTS (
    SELECT 1 
    FROM Users u 
    WHERE u.sUsrClientCode = Users.sUsrClientCode AND u.bUsrAdmin = true AND u.bUsrActive = true 
) AND Users.bUsrAdmin = false AND Users.bUsrActive = true; 

probabilmente andrò con l'ultima soluzione. Volevo solo sapere se è possibile fare ciò che voglio usando un join di sinistra.

+1

Cosa c'è che non va con il terzo? –

+1

Niente, funziona. Mi chiedo solo se posso farlo nell'altro modo usando join. Sembra più bello da vedere! Immagino che la performance sarebbe la stessa. – alfoks

+0

Il secondo dovrebbe funzionare (a prima vista) qual è l'errore che ottieni ?. Sei consapevole che la semantica della clausola 'FROM' è diversa in PostgreSQL rispetto a SQL Server? –

risposta

12

Ecco un modo generico per trasformare questa query aggiornamento dal modulo SQL-server PostgreSQL:

UPDATE Users 
SET bUsrActive = false 
WHERE 
ctid IN (
    SELECT u.ctid FROM Users u 
     LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1 
    WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL 
) 

ctid è una colonna pseudo che punta alla posizione unica di una riga. Potresti usare invece la chiave primaria della tabella se ne avesse una.

La query n. 2 della domanda non fa ciò che ci si aspetta perché la tabella aggiornata Users non è mai unita alla stessa tabella Users u nella clausola FROM. Proprio come quando si inserisce il nome di una tabella due volte in una clausola FROM, non vengono uniti o uniti in modo implicito, ma vengono considerati come due serie di righe indipendenti.

+0

Grazie per aver risposto. Sembra che ciò che sto chiedendo non possa essere fatto. Voglio dire, in caso di query n. 2, non esiste un modo per fare riferimento alla tabella u in qualche modo. Ad ogni modo avrò in mente la tua soluzione per riferimenti futuri e possibili domande più complesse. Per ora andrò con la terza query. – alfoks

1

Penso che questo sia il modo corretto di fare 2) Credo che sia più ottimale/efficiente di fare una selezione secondaria.

UPDATE Users uOrig 
    SET bUsrActive = false 
FROM Users u 
     LEFT JOIN Users u2 ON u.sUsrClientCode = u2.sUsrClientCode AND u2.bUsrAdmin = 1 AND u2.bUsrActive = 1 
WHERE u.bUsrAdmin = 0 AND u.bUsrActive = 1 AND u2.nkUsr IS NULL 
    and uOrig.sUsrClientCode = u.sUsrClientCode; 
+0

Non ho più Postgres installato e sono passati 2 anni dall'ultima volta che l'ho usato, ma credo che la tua query non sia corretta per la sintassi. Altrimenti anche la mia prima query funzionerebbe. Se ricordo bene, in Postgres non puoi fare il alias della tabella che stai aggiornando. – alfoks

+2

è possibile alias la tabella che si sta aggiornando. Non è possibile utilizzare questo alias nella clausola SET. –

+0

Questo non è sintatticamente corretto. –

Problemi correlati