2011-09-19 23 views
94

Mam kilka wierszy, które muszę wstawić do tabeli, ale te wstawki są zawsze wykonywane w partiach. Tak więc chcę sprawdzić, czy w tabeli istnieje jeden wiersz z partii, ponieważ wtedy wiem, że wszystkie zostały wstawione.Najszybsze sprawdzenie, czy istnieje wiersz w PostgreSQL

Nie jest to więc kontrola klucza podstawowego, ale nie powinna mieć większego znaczenia. Chciałbym tylko sprawdzić jeden wiersz, więc prawdopodobnie nie jest dobrze, więc jest to chyba coś w rodzaju exists.

Ale ponieważ jestem całkiem nowy w PostgreSQL, wolałbym zapytać ludzi, którzy wiedzą.

Moja partia zawiera wiersze z następującą strukturę:

userid | rightid | remaining_count 

Więc jeśli tabela zawiera wszystkie wiersze z warunkiem userid oznacza to wszystkie one są tam obecne.

+0

Chcesz sprawdzić, czy tabela ma JAKIEKOLWIEK wiersze lub wiersze z Twojej partii? – JNK

+0

dowolne wiersze z mojej partii tak. wszystkie one mają takie samo pole źle edytują. –

+0

Proszę wyjaśnić swoje pytanie. Chcesz dodać partię rekordów, wszystko lub nic? Czy jest coś specjalnego w hrabstwie? (BTW zastrzeżonym słowem, niepraktycznym jak nazwa kolumny) – wildplasser

Odpowiedz

174

Użyj ISTNIEJE słowo kluczowe dla true/false Powrót:

select exists(select 1 from contact where id=12) 
+9

Rozszerzenie na tym , możesz nazwać zwróconą kolumnę w celu łatwego odniesienia. Np. 'Wybierz istnieje (wybierz 1 z kontaktu gdzie id = 12) AS" istnieje "' – Rowan

+3

Jest to lepsze, ponieważ zawsze będzie zwracać wartość (prawda lub fałsz) zamiast czasami Brak (w zależności od twojego języka programowania), który może nie być rozszerzyć sposób, w jaki oczekujesz. – isaaclw

+1

Mam Seq Scan przy użyciu tej metody. Robię coś źle? – FiftiN

0
SELECT 1 FROM user_right where userid = ? LIMIT 1 

Jeśli zestaw wyników zawiera wiersz, nie trzeba go wstawiać. W przeciwnym razie wstaw swoje rekordy.

+0

jeśli paczka zawiera 100 wierszy, to zwróci mi 100 wierszy , myślisz, że to jest dobre? –

+0

Możesz ograniczyć go do 1 wiersza. Powinien działać lepiej. Spójrz na zredagowaną odpowiedź z @aix. –

0
select true from tablename where condition limit 1; 

Uważam, że jest to kwerenda używana przez PostgreSQL do sprawdzania kluczy obcych.

W twoim przypadku, można to zrobić za jednym razem zbyt:

insert into yourtable select $userid, $rightid, $count where not (select true from yourtable where userid = $userid limit 1); 
23

powiesz po prostu:

select 1 from tbl where userid = 123 limit 1; 

gdzie 123 jest userid partii, że jesteś o wstawianie .

Powyższe zapytanie zwróci pusty zestaw lub pojedynczy wiersz, w zależności od tego, czy istnieją rekordy z podanym identyfikatorem użytkownika.

Jeśli okaże się to zbyt wolne, można zajrzeć do tworzenia indeksu na tbl.userid.

jeśli nawet jednorzędowe z partii istnieje w tabeli, w takim razie ja nie trzeba wkładać moje wiersze, bo wiem na pewno wszyscy byli włożona.

Aby to pozostanie prawdą, nawet jeśli program zostanie przerwany w połowie partii, polecam, aby upewnić się, że zarządzanie transakcjami bazy odpowiednio (to znaczy, że cała partia zostaje włożona w ramach jednej transakcji).

+0

z pewnością używam transakcji –

+11

Czasami może być programowo łatwiej "wybrać liczbę (\ *) od (wybierz 1 ... limit 1)", ponieważ gwarantowane jest zawsze zwracanie wiersza z wartością liczby (\ *) 0 lub 1. –

+0

@DavidAldridge count (*) nadal oznacza, że ​​wszystkie wiersze muszą być przeczytane, podczas gdy limit 1 zatrzymuje się przy pierwszym rekordzie i zwraca – Imraan

8
INSERT INTO target(userid, rightid, count) 
    SELECT userid, rightid, count 
    FROM batch 
    WHERE NOT EXISTS (
    SELECT * FROM target t2, batch b2 
    WHERE t2.userid = b2.userid 
    -- ... other keyfields ... 
    )  
    ; 

BTW: jeśli chcesz całą partię na niepowodzenie w przypadku dwóch egzemplarzach, a następnie (otrzymują klucz podstawowy)

INSERT INTO target(userid, rightid, count) 
SELECT userid, rightid, count 
FROM batch 
    ; 

zrobi dokładnie to, co chcesz: albo uda lub zawiedzie.

+0

To sprawdzi każdy rząd. Chce zrobić jeden czek. – JNK

+0

Nie, wykonuje pojedynczą kontrolę. Podzapytowanie jest nieskorelowane. Wyskoczy, gdy znajdzie się jedna pasująca para. – wildplasser

+0

Zgadza się, myślałem, że odnosi się do zewnętrznego zapytania. +1 do ciebie – JNK

0

Jeśli myślisz o performance, może można użyć „Wykonaj” w funkcji tylko tak:

PERFORM 1 FROM skytf.test_2 WHERE id=i LIMIT 1; 
    IF FOUND THEN 
     RAISE NOTICE ' found record id=%', i; 
    ELSE 
     RAISE NOTICE ' not found record id=%', i; 
END IF; 
+0

nie działa ze mną: pojawia się błąd składniowy w pobliżu wykonania – Simon

+0

to jest pl/pgsql, nie SQL, stąd błąd składniowy dla "PERFORM", jeśli próbuję uruchomić go jako SQL –

0

Zasada

wybierz istnieje ( wybrać prawdziwe od xx gdzie xx ) jako „Does 1 + 1 Dodaj s do 2 ";

Powiązane problemy