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

अलग-अलग मापदंडों के साथ फ़ंक्शन में शून्य के लिए परीक्षण

मैं अन्य उत्तरों में कुछ सलाह से असहमत हूं। यह PL/pgSQL के साथ किया जा सकता है और मुझे लगता है कि यह ज्यादातर बहुत बेहतर . है क्लाइंट एप्लिकेशन में प्रश्नों को इकट्ठा करने के लिए। यह तेज़ और साफ-सुथरा है और ऐप अनुरोधों में केवल न्यूनतम वायर भेजता है। SQL कथन डेटाबेस के अंदर सहेजे जाते हैं, जिससे इसे बनाए रखना आसान हो जाता है - जब तक आप क्लाइंट एप्लिकेशन में सभी व्यावसायिक तर्क एकत्र नहीं करना चाहते, यह सामान्य वास्तुकला पर निर्भर करता है।

गतिशील SQL के साथ PL/pgSQL फ़ंक्शन

CREATE OR REPLACE FUNCTION func(
      _ad_nr       int  = NULL
    , _ad_nr_extra text = NULL
    , _ad_info     text = NULL
    , _ad_postcode text = NULL
    , _sname       text = NULL
    , _pname       text = NULL
    , _cname       text = NULL)
  RETURNS TABLE(id int, match text, score int, nr int, nr_extra text
              , info text, postcode text, street text, place text
              , country text, the_geom geometry)
  LANGUAGE plpgsql AS
$func$
BEGIN
   -- RAISE NOTICE '%', -- for debugging
   RETURN QUERY EXECUTE concat(
   $$SELECT a.id, 'address'::text, 1 AS score, a.ad_nr, a.ad_nr_extra
        , a.ad_info, a.ad_postcode$$

   , CASE WHEN (_sname, _pname, _cname) IS NULL THEN ', NULL::text' ELSE ', s.name' END  -- street
   , CASE WHEN (_pname, _cname) IS NULL         THEN ', NULL::text' ELSE ', p.name' END  -- place
   , CASE WHEN _cname IS NULL                   THEN ', NULL::text' ELSE ', c.name' END  -- country
   , ', a.wkb_geometry'

   , concat_ws('
   JOIN   '
   , '
   FROM   "Addresses" a'
   , CASE WHEN NOT (_sname, _pname, _cname) IS NULL THEN '"Streets"   s ON s.id = a.street_id' END
   , CASE WHEN NOT (_pname, _cname) IS NULL         THEN '"Places"    p ON p.id = s.place_id' END
   , CASE WHEN _cname IS NOT NULL                   THEN '"Countries" c ON c.id = p.country_id' END
   )

   , concat_ws('
   AND    '
      , '
   WHERE  TRUE'
      , CASE WHEN $1 IS NOT NULL THEN 'a.ad_nr = $1' END
      , CASE WHEN $2 IS NOT NULL THEN 'a.ad_nr_extra = $2' END
      , CASE WHEN $3 IS NOT NULL THEN 'a.ad_info = $3' END
      , CASE WHEN $4 IS NOT NULL THEN 'a.ad_postcode = $4' END
      , CASE WHEN $5 IS NOT NULL THEN 's.name = $5' END
      , CASE WHEN $6 IS NOT NULL THEN 'p.name = $6' END
      , CASE WHEN $7 IS NOT NULL THEN 'c.name = $7' END
   )
   )
   USING $1, $2, $3, $4, $5, $6, $7;
END
$func$;

कॉल करें:

SELECT * FROM func(1, '_ad_nr_extra', '_ad_info', '_ad_postcode', '_sname');

SELECT * FROM func(1, _pname := 'foo');

चूंकि सभी फ़ंक्शन पैरामीटर में डिफ़ॉल्ट मान होते हैं, आप स्थितीय . का उपयोग कर सकते हैं संकेतन, नामित संकेतन या मिश्रित फ़ंक्शन कॉल में आपके चयन पर संकेतन। देखें:

  • इनपुट पैरामीटर की परिवर्तनीय संख्या के साथ कार्य

डायनेमिक SQL की मूल बातें के लिए अधिक स्पष्टीकरण:

  • एक PL/pgSQL फ़ंक्शन को रिफ़ैक्टर करें ताकि विभिन्न SELECT क्वेरीज़ का आउटपुट लौटाया जा सके

concat() स्ट्रिंग के निर्माण के लिए फ़ंक्शन महत्वपूर्ण है। इसे Postgres 9.1 के साथ पेश किया गया था।

ELSE CASE . की शाखा स्टेटमेंट डिफ़ॉल्ट रूप से NULL . है जब मौजूद नहीं है। कोड को सरल करता है।

USING EXECUTE . के लिए क्लॉज SQL इंजेक्शन को असंभव बना देता है क्योंकि मानों को मानों . के रूप में पास किया जाता है और तैयार किए गए कथनों की तरह सीधे पैरामीटर मानों का उपयोग करने की अनुमति देता है।

NULL यहां पैरामीटर को अनदेखा करने के लिए मानों का उपयोग किया जाता है। वे वास्तव में खोज करने के अभ्यस्त नहीं हैं।

आपको SELECT . के आस-पास कोष्ठकों की आवश्यकता नहीं है RETURN QUERY . के साथ ।

साधारण SQL फ़ंक्शन

आप कर सकते थे इसे एक सादे SQL फ़ंक्शन के साथ करें और गतिशील SQL से बचें। कुछ मामलों के लिए यह तेज़ हो सकता है। लेकिन मुझे इस मामले में इसकी उम्मीद नहीं थी . अनावश्यक जुड़ाव और विधेय के बिना क्वेरी की योजना बनाना आमतौर पर सर्वोत्तम परिणाम देता है। इस तरह की एक साधारण क्वेरी के लिए योजना लागत लगभग नगण्य है।

CREATE OR REPLACE FUNCTION func_sql(
     _ad_nr       int  = NULL
   , _ad_nr_extra text = NULL
   , _ad_info     text = NULL
   , _ad_postcode text = NULL
   , _sname       text = NULL
   , _pname       text = NULL
   , _cname       text = NULL)
  RETURNS TABLE(id int, match text, score int, nr int, nr_extra text
              , info text, postcode text, street text, place text
              , country text, the_geom geometry)
  LANGUAGE sql AS 
$func$
SELECT a.id, 'address' AS match, 1 AS score, a.ad_nr, a.ad_nr_extra
     , a.ad_info, a.ad_postcode
     , s.name AS street, p.name AS place
     , c.name AS country, a.wkb_geometry
FROM   "Addresses"      a
LEFT   JOIN "Streets"   s ON s.id = a.street_id
LEFT   JOIN "Places"    p ON p.id = s.place_id
LEFT   JOIN "Countries" c ON c.id = p.country_id
WHERE ($1 IS NULL OR a.ad_nr = $1)
AND   ($2 IS NULL OR a.ad_nr_extra = $2)
AND   ($3 IS NULL OR a.ad_info = $3)
AND   ($4 IS NULL OR a.ad_postcode = $4)
AND   ($5 IS NULL OR s.name = $5)
AND   ($6 IS NULL OR p.name = $6)
AND   ($7 IS NULL OR c.name = $7)
$func$;

समान कॉल।

प्रभावी ढंग से NULL के साथ पैरामीटर को अनदेखा करने के लिए मान :

($1 IS NULL OR a.ad_nr = $1)

वास्तव में नल मानों को पैरामीटर के रूप में उपयोग करने के लिए , इसके बजाय इस निर्माण का उपयोग करें:

($1 IS NULL AND a.ad_nr IS NULL OR a.ad_nr = $1)  -- AND binds before OR

यह अनुक्रमणिका . के लिए भी अनुमति देता है उपयोग करने के लिए।
मौजूद मामले के लिए, LEFT JOIN के सभी उदाहरणों को बदलें JOIN के साथ ।

db<>फिडल यहाँ - साधारण डेमो . के साथ सभी प्रकार के लिए।
पुराना sqlfiddle

एसाइड्स

  • name का प्रयोग न करें और id कॉलम नामों के रूप में। वे वर्णनात्मक नहीं हैं और जब आप तालिकाओं के समूह में शामिल होते हैं (जैसे आप a lot . करते हैं एक रिलेशनल डेटाबेस में), आप name . नाम के कई कॉलम के साथ समाप्त होते हैं या id , और गड़बड़ी को छांटने के लिए उपनाम संलग्न करना होगा।

  • कृपया अपने SQL को ठीक से प्रारूपित करें, कम से कम सार्वजनिक प्रश्न पूछते समय। लेकिन इसे निजी तौर पर भी करें, अपने भले के लिए।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL में समवर्ती घटनाओं की संख्या की गणना करें

  2. Postgresql कुछ कुल राशि तक पहुंचने तक चयन करें

  3. PostgreSQL 8.3 के बाद से TPC-H का प्रदर्शन

  4. org.postgresql.util.PSQLException:ऑटो-प्रतिबद्ध मोड में बड़ी वस्तुओं का उपयोग नहीं किया जा सकता है

  5. postgresql - तालिका में प्रत्येक कॉलम की गणना (कोई शून्य मान नहीं)