PL / pgSQL'de bir sorgunun sonuç döndürüp döndürmediğini kontrol etmenin basit bir yolu var mı?


16

Şu anda PL / pgSQL ile biraz deniyorum ve böyle bir şey yapmak için daha zarif bir yol olup olmadığını bilmek istiyorum:

select c.data into data from doc c where c.doc_id = id and c.group_cur > group_cur order by c.id desc limit 1;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        select c.data into data from doc c where c.doc_id = id and c.global_cur > global_cur order by c.id desc limit 1;
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN NULL;

Yanıtlar:


21

İstisna blokları, koşulları kontrol etmek için değil, bindirme hataları içindir. Başka bir deyişle, bir koşul derleme zamanında ele alınabiliyorsa, hata olarak yakalanmamalı, sıradan program mantığı tarafından çözülmelidir.

In PL / PgSQL belgelerin Yakalama Hatalar bölümünde böyle bir ipucu bulabilirsiniz:

İpucu: Bir EXCEPTION yantümcesi içeren bir bloğun girilmesi ve çıkması, bir bloka sahip olmayan bir bloktan önemli ölçüde daha pahalıdır. Bu nedenle, EXCEPTION'ı gerek kalmadan kullanmayın.

İstisnalar (kötü) veya IF / THEN / ELSIF (daha iyi) kullanmak yerine, bunu tek bir sorguya yeniden yazabilirsiniz:

SELECT c.data into data
FROM  doc c
WHERE c.doc_id = id
  and (
    c.group_cur > group_cur
    or
    c.global_cur > global_cur
  )
ORDER BY
  -- this will make group always preferred over global
  case when c.group_cur > group_cur then 1 else 2 end ASC,
  -- and this is your normal ordering
  c.id DESC
limit 1;

Gerçekten iki sorgu istiyorsanız, önceki sorgunun sonuç verip vermediğini test etmek için özel FOUND değişkeni kullanabilirsiniz:

select c.data into data
from doc c
where c.doc_id = id and c.group_cur > group_cur
order by c.id desc limit 1;
if not found then
    select c.data into data
    from doc c
    where c.doc_id = id and c.global_cur > global_cur
    order by c.id desc limit 1;
    if not found then return null; end if;
end if;

Zorunlu RTFM bağlantıları folllow :-)

Bkz bu açıklaması için FOUNDdeğişken ve bu için IF/ THENbloklar.


13

Boole türünde özel bir FOUND değişkenini inceleyebilirsiniz. Belgelerden:

FOUND, her PL / pgSQL fonksiyon çağrısında yanlış başlar. Aşağıdaki ifade türlerinin her biri tarafından ayarlanır:

SELECT INTO ifadesi bir satır atanmışsa FOUND değerini, satır döndürülmediğinde false değerini ayarlar.

PERFORM deyimi, bir veya daha fazla satır üretirse (ve atarsa) FOUND değerini, satır üretilmezse false değerini ayarlar.

UPDATE, INSERT ve DELETE deyimleri, FOUND en az bir satır etkilenirse true, hiçbir satır etkilenmezse false olarak ayarlanır.

Bir FETCH deyimi bir satır döndürürse FOUND değerini, satır döndürülmediğinde false değerini ayarlar.

Bir MOVE deyimi, imleci başarıyla yeniden konumlandırırsa FOUND değerini yanlış, aksi halde false olarak ayarlar.

FOR veya FOREACH deyimi, bir veya daha fazla kez yinelenirse FOUND değerini yanlış, başka bir değer olarak ayarlar. FOUND, döngüden çıkıldığında bu şekilde ayarlanır; Döngünün yürütülmesi içinde, FOUND, döngü gövdesi içindeki diğer ifadelerin yürütülmesi ile değiştirilebilmesine rağmen, döngü ifadesi tarafından değiştirilmez.

Sorgu en az bir satır döndürürse, RETURN QUERY ve RETURN QUERY EXECUTE ifadeleri FOUND true, hiçbir satır döndürülmezse false olarak ayarlanır.

Diğer PL / pgSQL deyimleri FOUND'un durumunu değiştirmez. Özellikle EXECUTE öğesinin GET TANILAMA çıktısını değiştirdiğini, ancak BULUNAMADI değişmediğini unutmayın.

FOUND, her PL / pgSQL işlevi içindeki yerel bir değişkendir; herhangi bir değişiklik sadece geçerli işlevi etkiler.


ancak select intoveri döndürmeyen bir veri yine de bir istisna oluşturur
Jack diyor ki topanswers.xyz

3
genellikle hayır, sadece SEÇİM *
KAYIT

ah evet, benim hatam - bu OP örneğindeki istisna işleyicinin asla ateşlemeyeceği anlamına gelmiyor mu? :-)
Jack diyor ki topanswers.xyz

1
@JackDouglas: Hiçbir veri genellikle bir istisnanın nedeni değildir (yukarıdaki STRICT değiştiricisi gibi özel durumlar hariç). OP'nin burada bir yanılgısı vardı.
Erwin Brandstetter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.