चयनित कॉलम लौटाएं
CREATE OR REPLACE FUNCTION get_user_by_username(_username text
, _online bool DEFAULT false)
RETURNS TABLE (
user_id int
, user_name varchar
, last_activity timestamptz
)
LANGUAGE plpgsql AS
$func$
BEGIN
IF _online THEN
RETURN QUERY
UPDATE users u
SET last_activity = current_timestamp -- ts with time zone
WHERE u.user_name = _username
RETURNING u.user_id
, u.user_name
, u.last_activity;
ELSE
RETURN QUERY
SELECT u.user_id
, u.user_name
, u.last_activity
FROM users u
WHERE u.user_name = _username;
END IF;
END
$func$;
कॉल करें:
SELECT * FROM get_user_by_username('myuser', true);
आपके पास DECLARE result record;
लेकिन चर का उपयोग नहीं किया। मैंने क्रॉफ्ट को हटा दिया।
आप रिकॉर्ड को सीधे UPDATE
. से वापस कर सकते हैं , जो एक अतिरिक्त SELECT
. को कॉल करने से कहीं अधिक तेज़ है बयान। RETURN QUERY
का उपयोग करें और UPDATE
RETURNING
. के साथ खंड।
यदि उपयोगकर्ता _online
नहीं है , एक सादे के लिए डिफ़ॉल्ट SELECT
. यदि दूसरा पैरामीटर छोड़ दिया जाता है तो यह भी (सुरक्षित) डिफ़ॉल्ट है - जो उस डिफ़ॉल्ट को DEFAULT false
के साथ प्रदान करने के बाद ही संभव है फ़ंक्शन परिभाषा में।
यदि आप कॉलम नामों की तालिका-योग्यता नहीं रखते हैं (tablename.columnname
) फ़ंक्शन के अंदर प्रश्नों में, नामकरण विरोध . से सावधान रहें कॉलम नामों और नामित पैरामीटर के बीच, जो किसी फ़ंक्शन के अंदर हर जगह (अधिकांश) दृश्यमान होते हैं।
आप स्थितिगत संदर्भों ($n
का उपयोग करके भी ऐसे विरोधों से बच सकते हैं। ) मापदंडों के लिए। या ऐसे उपसर्ग का उपयोग करें जिसे आप कभी नहीं . करते हैं कॉलम नामों के लिए उपयोग करें:अंडरस्कोर की तरह (_username
)।
अगर users.username
परिभाषित किया गया है अद्वितीय अपनी तालिका में, फिर LIMIT 1
दूसरी क्वेरी में सिर्फ क्रूर है। अगर यह नहीं है , फिर UPDATE
एकाधिक पंक्तियों को अपडेट कर सकता है, जो संभवतः गलत है . मुझे लगता है कि एक अद्वितीय username
और शोर को कम करें।
फ़ंक्शन का वापसी प्रकार परिभाषित करें (जैसे @ertx प्रदर्शित) या आपको प्रत्येक फ़ंक्शन कॉल के साथ एक कॉलम परिभाषा सूची प्रदान करनी होगी, जो अजीब है।
उस उद्देश्य के लिए एक प्रकार बनाना (जैसे @ertx प्रस्तावित) एक वैध दृष्टिकोण है, लेकिन शायद एक समारोह के लिए अधिक हो सकता है। हमारे पास RETURNS TABLE
होने से पहले Postgres के पुराने संस्करणों में जाने का यही तरीका था उस उद्देश्य के लिए - जैसा कि ऊपर दिखाया गया है।
आपको लूप की आवश्यकता नहीं है इस सरल कार्य के लिए।
प्रत्येक फ़ंक्शन को भाषा घोषणा की आवश्यकता होती है। LANGUAGE plpgsql
इस मामले में।
मैं timestamptz
. का उपयोग करता हूं (timestamp with time zone
) के बजाय timestamp
(timestamp without time zone
), जो समझदार डिफ़ॉल्ट है। देखें:
- रेल और पोस्टग्रेएसक्यूएल में टाइम ज़ोन को पूरी तरह नज़रअंदाज़ करना
पूरी पंक्ति (पंक्तियों) का रिटर्न (सेट)
सभी कॉलम लौटाने के लिए मौजूदा तालिका में users
, एक आसान तरीका है। Postgres स्वचालित रूप से प्रत्येक तालिका के लिए समान नाम का मिश्रित प्रकार . परिभाषित करता है . बस RETURNS SETOF users
. का उपयोग करें क्वेरी को व्यापक रूप से सरल बनाने के लिए:
CREATE OR REPLACE FUNCTION get_user_by_username(_username text
, _online bool DEFAULT false)
RETURNS SETOF users
LANGUAGE plpgsql AS
$func$
BEGIN
IF _online THEN
RETURN QUERY
UPDATE users u
SET last_activity = current_timestamp
WHERE u.user_name = _username
RETURNING u.*;
ELSE
RETURN QUERY
SELECT *
FROM users u
WHERE u.user_name = _username;
END IF;
END
$func$;
पूरी पंक्ति और कस्टम जोड़ लौटाएं
नीचे टिप्पणी में TheRealChx101 द्वारा जोड़े गए प्रश्न का समाधान करने के लिए:
<ब्लॉकक्वॉट>क्या होगा यदि आपके पास एक संपूर्ण तालिका के अतिरिक्त एक परिकलित मूल्य भी है?
इतना आसान नहीं, लेकिन करने योग्य। हम पूरी पंक्ति प्रकार को एक . के रूप में भेज सकते हैं फ़ील्ड, और अधिक जोड़ें:
CREATE OR REPLACE FUNCTION get_user_by_username3(_username text
, _online bool DEFAULT false)
RETURNS TABLE (
users_row users
, custom_addition text
)
LANGUAGE plpgsql AS
$func$
BEGIN
IF _online THEN
RETURN QUERY
UPDATE users u
SET last_activity = current_timestamp -- ts with time zone
WHERE u.user_name = _username
RETURNING u -- whole row
, u.user_name || u.user_id;
ELSE
RETURN QUERY
SELECT u, u.user_name || u.user_id
FROM users u
WHERE u.user_name = _username;
END IF;
END
$func$;
"मैजिक" फ़ंक्शन कॉल में है, जहां हम (वैकल्पिक रूप से) पंक्ति प्रकार को विघटित करते हैं:
SELECT (users_row).*, custom_addition FROM get_user_by_username('foo', true);
db<>फिडल यहाँ (सभी दिखा रहा है)
अगर आपको कुछ और "गतिशील" चाहिए, तो इस पर विचार करें:
- एक PL/pgSQL फ़ंक्शन को रिफ़ैक्टर करें ताकि विभिन्न SELECT क्वेरीज़ का आउटपुट लौटाया जा सके