यह अपेक्षित, प्रलेखित व्यवहार है।
टॉम लेन इसे यहाँ बताते हैं।
यहाँ मैनुअल में प्रलेखित:
डाटा में सुधार करने वाले बयान में WITH
ठीक एक बार क्रियान्वित कर रहे हैं, और
हमेशा पूरा करने , चाहे की स्वतंत्र रूप से प्राथमिक क्वेरी उनके उत्पादन के सभी (या वास्तव में किसी भी) पढ़ता है। ध्यान दें कि यह इसके लिए नियम से अलग SELECT
है WITH
: जैसा कि पिछले अनुभाग में कहा गया है, का निष्पादन SELECT
केवल उसी रूप में किया जाता है जहां तक प्राथमिक क्वेरी इसके आउटपुट की मांग करती है ।
बोल्ड जोर मेरा। "डेटा-संशोधन" हैं INSERT
, UPDATE
और DELETE
क्वेरीज़। (जैसा विरोध किया गया SELECT
।) एक बार फिर मैनुअल:
आप (डेटा में सुधार करने वाले बयानों का उपयोग कर सकते INSERT
, UPDATE
या DELETE
) में WITH
।
उचित कार्य
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;
मैंने डिफ़ॉल्ट (शोर) क्लॉस को गिरा दिया और
STRICT
इसका संक्षिप्त पर्यायवाची हैRETURNS NULL ON NULL INPUT
।
किसी तरह सुनिश्चित करें कि पैरामीटर नाम कॉलम नामों के साथ संघर्ष न करें। मैं आगे बढ़ा _
, लेकिन यह सिर्फ मेरी व्यक्तिगत पसंद है।
अगर मैं सुझाव दे coin
सकता NULL
हूं:
SET coin = CASE WHEN coin IS NULL THEN _coins ELSE coin + _coins END
तो users.id
, प्राथमिक कुंजी है तो न तो RETURNS TABLE
है और न ही ROWs 1000
कोई मतलब। केवल एक पंक्ति को अद्यतन / वापस किया जा सकता है। लेकिन यह सब मुख्य बिंदु के बगल में है।
उचित कॉल करें
यह RETURNING
आपके फ़ंक्शन से क्लॉज़ और रिटर्न मान का उपयोग करने का कोई मतलब नहीं है यदि आप किसी भी तरह से कॉल में दिए गए मानों को अनदेखा करने जा रहे हैं। यह भी कोई मतलब नहीं है कि SELECT * FROM ...
अगर आप उन्हें वैसे भी अनदेखा करते हैं तो लौटी हुई पंक्तियों को विघटित करना।
बस एक अदिश स्थिरांक लौटें ( RETURNING 1
), फ़ंक्शन को इस रूप में परिभाषित करें RETURNS int
(या RETURNING
पूरी तरह से छोड़ दें और इसे बनाएं RETURNS void
) और इसके साथ कॉल करेंSELECT my_function(...)
समाधान
जब से तुम ...
वास्तव में परिणाम के बारे में परवाह नहीं है
.. बस SELECT
एक निरंतर रूप CTE। इसे तब तक निष्पादित किए जाने की गारंटी है जब तक इसे बाहरी SELECT
(प्रत्यक्ष या अप्रत्यक्ष रूप से) में संदर्भित किया जाता है ।
WITH test AS (SELECT __post_users_id_coin(10, 1))
SELECT 1 FROM test;
यदि आपके पास वास्तव में एक सेट-रिटर्निंग फ़ंक्शन है और फिर भी आउटपुट के बारे में परवाह नहीं है:
WITH test AS (SELECT * FROM __post_users_id_coin(10, 1))
SELECT 1 FROM test LIMIT 1;
1 पंक्ति से अधिक वापस जाने की आवश्यकता नहीं है। फ़ंक्शन को अभी भी कहा जाता है।
अंत में, यह स्पष्ट नहीं है कि आपको शुरू करने के लिए सीटीई की आवश्यकता क्यों है। शायद सिर्फ अवधारणा का एक प्रमाण।
बारीकी से संबंधित:
SO पर संबंधित उत्तर:
और विचार करें: