Bu beklenen, belgelenmiş davranış.
Tom Lane bunu burada açıklıyor.
Buradaki kılavuzda belgelenmiştir:
İfadeleri Veri değiştirici içinde WITH
tam olarak bir kez yürütülür ve
her zaman tamamlanma , bağımsız bir şekilde, ister primer sorgu kendi çıkış (aslında ya da herhangi bir) bütün okur. Uyarı Bunun kuraldan farklı olduğunu SELECT
içinde WITH
: Bir önceki bölümde belirtildiği gibi, bir yürütülmesi SELECT
sadece primer sorgu çıkışını talep olarak yapılır .
Cesur vurgu benim. "Veri modifiye" dir INSERT
, UPDATE
ve DELETE
sorgular. (Aksine SELECT
.). Kılavuz bir kez daha:
Sen (veri modifiye ifadeleri kullanabilir INSERT
, UPDATE
ya da DELETE
) içinde WITH
.
Uygun fonksiyon
CREATE OR REPLACE FUNCTION public.__post_users_id_coin (_coins integer, _userid integer)
RETURNS TABLE (id integer) AS
$func$
UPDATE users u
SET coin = u.coin + _coins -- see below
WHERE u.id = _userid
RETURNING u.id
$func$ LANGUAGE sql COST 100 ROWS 1000 STRICT;
Ben varsayılan (gürültü) yan tümceleri düştü ve
STRICT
kısa eşanlamlıRETURNS NULL ON NULL INPUT
.
Parametre adlarının bir şekilde sütun adlarıyla çakışmadığından emin olun. Ben _
tercih ettim, ama bu sadece benim kişisel tercihim.
Eğer coin
olabilir NULL
ben öneririz:
SET coin = CASE WHEN coin IS NULL THEN _coins ELSE coin + _coins END
Eğer users.id
o zaman, birincil anahtar ne RETURNS TABLE
de ROWs 1000
herhangi bir anlam ifade etmiyor. Yalnızca tek bir satır güncellenebilir / döndürülebilir. Ama hepsi ana noktanın yanında.
Uygun çağrı
Yine RETURNING
de çağrıda döndürülen değerleri yoksayarsanız, fıkra ve işlevinizden döndürülen değerleri kullanmak mantıklı değildir . Ayrıca, SELECT * FROM ...
yine de yoksayarsanız , döndürülen satırları ayrıştırmanın bir anlamı yoktur .
Sadece bir skaler sabit ( RETURNING 1
) döndürün, işlevi olarak tanımlayın RETURNS int
(veya RETURNING
tamamen bırakın ve yapın RETURNS void
) veSELECT my_function(...)
Çözüm
Senden beri ...
sonucu gerçekten umursamıyorum
.. sadece SELECT
CTE'nin sabit bir formudur. Dışta SELECT
(doğrudan veya dolaylı olarak) belirtildiği sürece yürütülmesi garanti edilir .
WITH test AS (SELECT __post_users_id_coin(10, 1))
SELECT 1 FROM test;
Aslında bir set-döndürme fonksiyonunuz varsa ve yine de çıktıyı umursamıyorsanız:
WITH test AS (SELECT * FROM __post_users_id_coin(10, 1))
SELECT 1 FROM test LIMIT 1;
1'den fazla satır döndürmeye gerek yok. İşlev hala çağrılır.
Son olarak, başlamak için neden CTE'ye ihtiyacınız olduğu belirsizdir. Muhtemelen sadece bir kavram kanıtı.
Yakından alakalı:
SO ile ilgili cevap:
Ve düşünün: