2013-01-24 12 views
9

Jestem nowa w PostgreSQL i próbuję przekonwertować zapytanie z SQL Server.Aktualizacja PostgreS z lewej strony

Mam tabelę Użytkownicy z, między innymi, kolumnami bUsrActive, bUsrAdmin i sUsrClientCode. Chcę zaktualizować użytkowników i ustawić bUsrActive = false, jeśli nie istnieje inny użytkownik o tym samym kodzie SUsrClientCode, gdzie bUsrAdmin = true i bUsrActive = true.

W SQL Server Mam tego zapytania

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 

Próbuję przekonwertować to do PostgreSQL. Napisałem 3 podejścia.

1) Moja pierwsza próba. Oczywiście nie działa.

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) Rozumiem, dlaczego nie działa (aktualizuje wszystkich użytkowników). Po prostu nie mogę dowiedzieć się, jak mogę odwołać się do użytkowników tabeli u w części 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) Następujące działa, ale nie przy użyciu sprzężenia.

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; 

Prawdopodobnie pójdę z ostatnim rozwiązaniem. Chciałem tylko wiedzieć, czy można zrobić to, co chcę, używając lewostronnego połączenia.

+1

Co jest nie tak z trzecim? –

+1

Nic, działa. Zastanawiam się, czy mogę to zrobić w inny sposób, używając złączeń. Wydaje się ładniejszy dla oka! Myślę, że wydajność byłaby taka sama. – alfoks

+0

Drugi powinien działać (na pierwszy rzut oka), jaki jest błąd. Czy wiesz, że semantyka klauzuli "OD" jest inna w PostgreSQL w porównaniu do SQL Server? –

Odpowiedz

12

Oto ogólny sposób, aby przekształcić to zapytanie z formularza aktualizacji serwera SQL do 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 jest pseudo-kolumna, która zwraca uwagę na wyjątkową lokalizację z rzędu. Zamiast tego można użyć klucza podstawowego tabeli, jeśli taki był.

Pytanie nr 2 z pytania nie spełnia oczekiwań, ponieważ zaktualizowana tabela Users nigdy nie jest dołączona do tej samej tabeli Users u w klauzuli FROM. Podobnie jak w przypadku dwukrotnego umieszczenia nazwy tabeli w klauzuli FROM, nie są one niejawnie połączone lub powiązane, są one traktowane jako dwa niezależne zestawy wierszy.

+0

Dzięki za odpowiedź. Wygląda na to, że tego, o co proszę, nie da się zrobić. Chodzi mi o to, że w przypadku zapytania nr 2 nie sposób jakoś odwołać się do tabeli. W każdym razie będę miał na uwadze twoje rozwiązanie na przyszłość i możliwe bardziej złożone zapytania. Na razie przejdę do trzeciego zapytania. – alfoks

1

Myślę, że to jest właściwy sposób na wykonanie 2) Uważam, że jest bardziej optymalny/skuteczny niż robienie subselekcji.

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

Nie mam już zainstalowanego PostgreSQL i minęły 2 lata, odkąd ostatni raz go używałem, ale uważam, że twoje zapytanie nie jest poprawne pod względem składni. W przeciwnym razie moje pierwsze zapytanie również by działało. Jeśli dobrze pamiętam, w Postgresie nie można alias tabeli, którą aktualizujesz. – alfoks

+2

możesz alias aktualizowanej tabeli. Nie możesz użyć tego aliasu w klauzuli SET. –

+0

To nie jest poprawna składniowo. –

Powiązane problemy