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

पीएल/पीजीएसक्यूएल फ़ंक्शन से अज्ञात कॉलम के साथ गतिशील तालिका लौटाएं

इसे हल करना कठिन है, क्योंकि SQL कॉल समय पर रिटर्न प्रकार जानने की मांग करता है .
साथ ही, एक plpgsql फ़ंक्शन के लिए एक अच्छी तरह से परिभाषित रिटर्न प्रकार होना चाहिए ।

अगर आप गुमनाम रिकॉर्ड लौटाना चुनते हैं , आपको वह मिलता है जो आपने परिभाषित किया था:अनाम रिकॉर्ड। Postgres को नहीं पता कि अंदर क्या है। इसलिए, एक कॉलम परिभाषा सूची आवश्यक है प्रकार को विघटित करने के लिए।

सटीक आवश्यकताओं के आधार पर विभिन्न समाधान हैं। यदि आपके पास कॉल के समय . रिटर्न प्रकार जानने का कोई तरीका है , मेरा सुझाव है बहुरूपी प्रकार जैसा कि इस उत्तर के अंतिम अध्याय ("विभिन्न पूर्ण तालिका प्रकार") में उल्लिखित है:
विभिन्न चयन प्रश्नों के आउटपुट को वापस करने के लिए एक PL/pgSQL फ़ंक्शन को रिफैक्टर करें

लेकिन इसमें रिटर्न टाइप फंक्शन के अंदर रनटाइम पर . में एक और कॉलम जोड़ना शामिल नहीं है . यह संभव नहीं है। मैं पूरे दृष्टिकोण पर पुनर्विचार करूंगा

जहाँ तक आपके वर्तमान दृष्टिकोण का सवाल है, मैं जिस निकटतम चीज़ के बारे में सोच सकता हूँ वह एक अस्थायी तालिका (या एक कर्सर) होगी, जिसे आप दूसरी कॉल में क्वेरी करते हैं। एक एकल लेन-देन . के भीतर ।

आपको आपके कोड में कुछ अन्य समस्याएं हैं . नीचे नोट देखें।

अवधारणा का प्रमाण

CREATE OR REPLACE FUNCTION f_tbl_plus_infowindow (_tbl regclass) -- regclass!
  RETURNS void AS  -- no direct return type
$func$
DECLARE
   -- appending _tmp for temp table
   _tmp text := quote_ident(_tbl::text || '_tmp');
BEGIN

-- Create temp table only for duration of transaction
EXECUTE format(
   'CREATE TEMP TABLE %s ON COMMIT DROP AS TABLE %s LIMIT 0', _tmp, _tbl);

IF EXISTS (
   SELECT 1
   FROM   pg_attribute a
   WHERE  a.attrelid = _tbl
   AND    a.attname  = 'infowindow'
   AND    a.attisdropped = FALSE)
THEN
   EXECUTE format('INSERT INTO %s SELECT * FROM %s', _tmp, _tbl);
ELSE
  -- This is assuming a NOT NULL column named "id"!
   EXECUTE format($x$
      ALTER  TABLE %1$s ADD COLUMN infowindow text;
      INSERT INTO %1$s
      SELECT *, 'ID: ' || id::text
      FROM   %2$s $x$
     ,_tmp, _tbl);
END IF;

END
$func$ LANGUAGE plpgsql;

कॉल को एक ही लेन-देन में होना चाहिए। आपको अपने क्लाइंट के आधार पर एक स्पष्ट लेनदेन शुरू करना पड़ सकता है।

BEGIN;
SELECT f_tbl_plus_infowindow ('tbl');
SELECT * FROM tbl_tmp;  -- do something with the returned rows
ROLLBACK;               -- or COMMIT, does not matter here

एसक्यूएल फिडल.

वैकल्पिक रूप से आप सत्र की अवधि के लिए अस्थायी तालिका को रहने दे सकते हैं। हालांकि, बार-बार कॉल के साथ टकराव के नामकरण से सावधान रहें।

नोट

  • पुराने ALIAS . के बजाय पैरामीटर नामों का उपयोग करें आदेश।

  • वर्तमान स्कीमा में वास्तव में "डिफ़ॉल्ट" के लिए, मेरे द्वारा प्रदर्शित सरल क्वेरी का उपयोग करें। regclass का उपयोग करना चाल स्वचालित रूप से करता है। विवरण:

    • तालिका नाम PostgreSQL फ़ंक्शन पैरामीटर के रूप में

    इसके अलावा, यह सिंटैक्स त्रुटियों और संभव SQL इंजेक्शन . से भी बचा जाता है आपके मूल कोड में गैर-मानक (या दुर्भावनापूर्ण रूप से विकृत) तालिका नामों से।

  • आपके ELSE . में कोड क्लॉज बिल्कुल भी काम नहीं करेगा।

  • TABLE tbl; SELECT * FROM tbl; . के लिए मूल रूप से छोटा है ।

  • format() . पर विवरण मैनुअल में।




  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. रूबी-ऑन-रेल के साथ उपयोग के लिए विंडोज़ पर पोस्टग्रेज़ स्थापित करना

  3. नेस्टेड केस को सरल बनाएं जब स्टेटमेंट

  4. PostgreSQL में पावर () फ़ंक्शन कैसे काम करता है

  5. SQLAlchemy और कई प्रक्रियाओं के साथ कनेक्शन की समस्या