PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

PostgreSQL:त्रुटि:42601:रिकॉर्ड लौटाने वाले कार्यों के लिए एक कॉलम परिभाषा सूची की आवश्यकता होती है

चयनित कॉलम लौटाएं

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 क्वेरीज़ का आउटपुट लौटाया जा सके


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL के साथ डेटाबेस के बीच डेटा ट्रांसफर करें

  2. PostgreSQL अनुक्रमों का अगला मान?

  3. Linux पर PostgreSQL डेटाबेस डिफ़ॉल्ट स्थान

  4. पोस्टग्रेज कॉलम मौजूद नहीं है

  5. PostgreSQL 12 में प्रगति रिपोर्टिंग संवर्द्धन