यह अपेक्षित, प्रलेखित व्यवहार है।
टॉम लेन इसे यहाँ बताते हैं।
यहाँ मैनुअल में प्रलेखित:
डाटा में सुधार करने वाले बयान में 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 पर संबंधित उत्तर:
और विचार करें: