2012-08-09 17 views
31

PL/pgSQL'de bir işlev yazıyorum ve bir satır olup olmadığını kontrol etmenin en kolay yolunu arıyorum.
Şu anda bir integer SELECT, bir boolean, gerçekten çalışmıyor. Bunu yapmanın en iyi yolunu bilecek kadar PL/pgSQL ile yaşamadım.PL/pgSQL bir satır mevcut olup olmadığını kontrol etme

İşte benim işlevinin parçası:

DECLARE person_exists boolean; 
BEGIN 

person_exists := FALSE; 

SELECT "person_id" INTO person_exists 
    FROM "people" p 
WHERE p.person_id = my_person_id 
LIMIT 1; 

IF person_exists THEN 
    -- Do something 
END IF; 

END; $$ LANGUAGE plpgsql; 

Güncelleme - şimdilik böyle bir şey yapıyorum:

DECLARE person_exists integer; 
BEGIN 

person_exists := 0; 

SELECT count("person_id") INTO person_exists 
    FROM "people" p 
WHERE p.person_id = my_person_id 
LIMIT 1; 

IF person_exists < 1 THEN 
    -- Do something 
END IF; 

cevap

90

Daha kısa, daha hızlı:EXISTS.

IF EXISTS (SELECT 1 FROM people WHERE person_id = my_person_id) THEN 
    -- do something 
END IF; 

sorgu planlayıcısı bulunan ilk satırda durdurabilir - count() aksine, ne olursa olsun tüm eşleşen satırları tarar hangi. Büyük masalarla fark yaratır. Eşsiz bir sütun üzerinde bir koşulla zorlukla - sadece bir satır zaten geçerlidir (ve hızlı bir şekilde bakmak için bir dizin var).

Aşağıdaki yorumlarda @a_horse_with_no_name numaralı girişten geliştirmeler yapılmıştır.

+0

İyi nokta! (Person_id muhtemelen birincil anahtar olmasına rağmen, bu nedenle sadece bir dizin araması kullanarak tek bir tabloyu "tarar". –

+0

@a_horse_with_no_name: Şu an itibariyle (Postgres 9.1) 'count()' * her zaman * sıralı bir taramayı tetikler. Herhangi bir tablo ile tPL'den ANALİZ SEÇİMİ seçimini (id) deneyin. Daha fazlası [Postgres Wiki'de yavaş sayma] (http://wiki.postgresql.org/wiki/Slow_Counting). Postgres 9.2'nin yeni sadece dizin taraması bazı şeyleri geliştirmesi gerekiyordu, çünkü (bazı koşullar sağlanmışsa) "sayım (id)" için bir indeks taraması kullanabiliyordu - yine de bunu kendi başıma denemek ve görmek zorunda kaldım .. –

+3

A 'koşullu * (*) * ile * (özellikle PK sütununda değil) ** sıralı bir taramayı tetiklemez. –

2

Kullanım sayımı (*)

declare 
    cnt integer; 
begin 
    SELECT count(*) INTO cnt 
    FROM people 
    WHERE person_id = my_person_id; 

IF cnt > 0 THEN 
    -- Do something 
END IF; 

Edit (downvoter için) Açıklamaları okuyan kimseyi ve benzeri olmayan bir şeyi okuyanlar)

Çözüm, bir sütun üzerinde bir yan tümce olduğu için (yalnızca sütunun adı birincil anahtar olduğunu gösterir) etkili olduğu için etkindir. Bu nedenle, tümce son derece etkilidir)

Bu nedenle, where tümcesinde birincil anahtar tarafından tanımlanan bir satırın varlığını sınamak için LIMIT veya başka bir şeye gerek yoktur. Bunu test etmek için ,'un etkili bir yoludur.

+0

Haha Bu çözümü yayınladığınız gibi gönderdim. – nnyby

+2

Bu amaç için COUNT kullanmayın - bu performans sorunudur - ya da türetilmiş tabloyu kullanmalısınız SELECT COUNT (*) FROM (SELECT * from people LIMIT 1) x –

+1

@PavelStehule: "where" durumu olduğunda bile ** birincil anahtar **? Bunun senin açıklamandan çok daha yavaş olacağını hayal bile edemiyorum. İcra planı, her iki çözüm için de hemen hemen aynıdır. –

İlgili konular