इसे और सरल और बेहतर बनाया जा सकता है:
CREATE OR REPLACE FUNCTION some_f(_tbl regclass, OUT result integer)
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format('SELECT (EXISTS (SELECT FROM %s WHERE id = 1))::int', _tbl)
INTO result;
END
$func$;
स्कीमा-योग्य नाम से कॉल करें (नीचे देखें):
SELECT some_f('myschema.mytable'); -- would fail with quote_ident()
या:
SELECT some_f('"my very uncommon table name"');
प्रमुख बिंदु
एक OUT
का प्रयोग करें पैरामीटर समारोह को सरल बनाने के लिए। आप इसमें सीधे डायनेमिक SQL के परिणाम का चयन कर सकते हैं और किया जा सकता है। अतिरिक्त चर और कोड की कोई आवश्यकता नहीं है।
EXISTS
ठीक वही करता है जो आप चाहते हैं। आपको true
मिलता है यदि पंक्ति मौजूद है या false
अन्यथा। ऐसा करने के कई तरीके हैं, EXISTS
आम तौर पर सबसे कुशल है।
ऐसा लगता है कि आप एक पूर्णांक . चाहते हैं वापस, इसलिए मैंने boolean
कास्ट किया EXISTS
. से परिणाम से integer
, जो ठीक वही देता है जो आपके पास था। मैं बूलियन लौटूंगा इसके बजाय।
मैं वस्तु पहचानकर्ता प्रकार का उपयोग करता हूं regclass
_tbl
. के लिए इनपुट प्रकार के रूप में . यह सब कुछ करता है quote_ident(_tbl)
या format('%I', _tbl)
करेंगे, लेकिन बेहतर, क्योंकि:
-
.. यह SQL इंजेक्शन को रोकता है ठीक वैसे ही।
-
.. यदि तालिका का नाम अमान्य है/मौजूद नहीं है/वर्तमान उपयोगकर्ता के लिए अदृश्य है तो यह तुरंत और अधिक शानदार ढंग से विफल हो जाता है। (एक
regclass
पैरामीटर केवल मौजूदा . के लिए लागू होता है टेबल।) -
.. यह स्कीमा-योग्य तालिका नामों के साथ काम करता है, जहां एक सादा
quote_ident(_tbl)
याformat(%I)
असफल होंगे क्योंकि वे अस्पष्टता का समाधान नहीं कर सकते। आपको स्कीमा और टेबल नामों को अलग-अलग पास करना होगा और बचना होगा।
यह केवल मौजूदा . के लिए काम करता है टेबल, जाहिर है।
मैं अब भी format()
. का उपयोग करता हूं , क्योंकि यह वाक्य रचना को सरल करता है (और यह प्रदर्शित करने के लिए कि इसका उपयोग कैसे किया जाता है), लेकिन %s
के साथ %I
. के बजाय . आमतौर पर, क्वेरी अधिक जटिल होती हैं इसलिए format()
अधिक मदद करता है। सरल उदाहरण के लिए हम केवल एक साथ जोड़ सकते हैं:
EXECUTE 'SELECT (EXISTS (SELECT FROM ' || _tbl || ' WHERE id = 1))::int'
id
में टेबल-क्वालिफाई करने की कोई जरूरत नहीं है कॉलम जबकि FROM
. में केवल एक ही टेबल है सूची। इस उदाहरण में कोई अस्पष्टता संभव नहीं है। (डायनामिक) SQL कमांड EXECUTE
. के अंदर है एक अलग दायरा . रखें , फ़ंक्शन चर या पैरामीटर वहां दिखाई नहीं दे रहे हैं - फ़ंक्शन बॉडी में सादे SQL कमांड के विपरीत।
यही कारण है कि आप हमेशा डायनामिक SQL के लिए उपयोगकर्ता इनपुट से ठीक से बचें:
db<>फिडल यहाँ SQL इंजेक्शन का प्रदर्शन
पुराना sqlfiddle