2016-10-11 71 views
6

PL/pgSQL içinde bir çift iç içe geçmiş (veya iç) işlevle bir işlev oluşturmak istiyorum. Bu sayede problemi daha küçük parçalara ayırabilirim fakat küçük parçalara bu fonksiyonun dışında erişemiyorum.PL/pgSQL'de yuvalanmış bir işlevi nasıl oluştururum?

Bunu PL/pgSQL'de yapmak mümkün müdür? Öyleyse nasıl?

+0

Bunu neden yaptın? Bana pratik olmayan görünüyor. Sorunu birçok işlev olmaksızın daha küçük parçalara bölebilir veya gerçekten ihtiyacınız varsa bunları üzerlerinde ayarlayabilirsiniz. –

cevap

2

İç içe geçmiş işlevler PLpgSQL tarafından desteklenmemektedir. Emülasyonun hiçbir anlamı yoktur ve üretken değildir.

+1

İlk bakışta kivi tarafından açıklanan emülasyon işe yaradı. Daha küçük veri setleri üzerinde test ettim ve iyi görünüyordu. Ancak, büyük tarihçelerle çalışırken, her zaman çok garip kilitleme hataları ile başarısız oldu. Bunu okuyan herkesin bir iç içe geçmiş işlevleri PL/pgSQL'de çalışmaya zorlamaya çalışmakla en iyi şekilde sunulacağını düşünüyorum. –

+0

@GregoryArenius: Bu örnekle oynamıştım, "dışsal" işlevi çağrıldığında "iç" ("dış" işlevle aynı kapsamda) işlevini yaratır/değiştirir, dolayısıyla garip hatalar. Bu bir "içsel işlev" değildir ve "dış" ın içsel kapsamına da erişemez. –

7

Deneyin: Postgres'e olarak

CREATE OR REPLACE FUNCTION outer() RETURNS void AS $outer$ 
DECLARE s text; 
BEGIN 
    CREATE OR REPLACE FUNCTION inner() RETURNS text AS $inner$ 
    BEGIN 
    RETURN 'inner'; 
    END; 
    $inner$ language plpgsql; 

    SELECT inner() INTO s; 
    RAISE NOTICE '%', s; 

    DROP FUNCTION inner(); 
END; 
$outer$ language plpgsql; 

9,5 SELECT outer(); çıkışları

psql:/vagrant/f.sql:14: NOTICE: inner 

EDIT: Eğer dış işlevi sonunda iç fonksiyonunu düşürmeyin eğer görülmeye devam edecektir veritabanının geri kalanı.

+2

Bunu deneyen birisine işaret etmek için birkaç şey: Hem iç hem de dış fonksiyon için 'AS $$' özelliğini kullanamazsınız. Ayrıca, işlevinizin argümanları varsa, bu işlevi bıraktığınızda türleri iletmeniz gerekir. Ve işlevlerinizi henüz oluşturulmadıkları için dış işlevin 'DECLARE 'kısmında arayamazsınız. İç içe geçmiş işlevlerin oluşturulmasından sonra değişkeni oluşturun ve ona bir değer atayın. –

+2

@Gregory: Daha önemli bir nokta: Eğer iki eşzamanlı işlem bu fonksiyonu çağırmaya çalışırsa, ikincisi, veritabanı isimlerinin işlev adlarına ilişkin benzersizliği nedeniyle, ilk olana kadar "CREATE" ini engelleyecektir. İçsel işlevi oturumunuzun geçici şemasına yerleştirerek, yani CREATE FUNCTION pg_temp.inner() 'işlevini kullanarak çalışabilirsiniz. Eklenen fayda, iç işlevlerin hiçbir zaman dışarıdan görülemeyecekleri ve oturumunuzdan sonra otomatik olarak temizlendikleridir. –

+2

@Gregory: Bu arada, "DECLARE ... BEGIN ... END" blokları iç içe olabilir, böylece iç fonksiyon oluşturulduktan sonra bildirimlerinizi yapabilirsiniz –