आपका कार्य इस तरह दिख सकता है:
CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)
RETURNS SETOF transactions AS
$BODY$
BEGIN
RETURN QUERY EXECUTE '
SELECT *
FROM transactions
WHERE ' || quote_ident(_col) || ' = $1
LIMIT $2'
USING _val, _limit;
END;
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER;
पोस्टग्रेएसक्यूएल में 9.1 या बाद में यह format()
...
RETURN QUERY EXECUTE format('
SELECT *
FROM transactions
WHERE %I = $1
LIMIT $2', _col)
USING _val, _limit;
...
%I
quote_ident()
. जैसे पहचानकर्ताओं से बच निकलता है ।
प्रमुख बिंदु:
-
आप डायनेमिक SQL की सीमा से टकरा रहे थे कि आप पहचानकर्ताओं के लिए मापदंडों का उपयोग नहीं कर सकते। आपको कॉलम नाम के साथ क्वेरी स्ट्रिंग बनानी होगी और फिर इसे निष्पादित करें।
-
हालांकि आप इसे मूल्यों के साथ कर सकते हैं। मैं
USING
. के उपयोग को प्रदर्शित करता हूंEXECUTE
. के लिए क्लॉज .quote_ident()
:SQL इंजेक्शन और कुछ सिंटैक्स त्रुटियों को रोकता है। -
मैंने आपके कार्य को काफी हद तक सरल बना दिया है।
[RETURN QUERY EXECUTE][3]
आपके कोड को छोटा और तेज़ बनाता है। यदि आप केवल पंक्ति वापस करते हैं तो लूप करने की कोई आवश्यकता नहीं है। -
मैं नाम का उपयोग करता हूं
IN
पैरामीटर, ताकि आप क्वेरी स्ट्रिंग में $-नोटेशन के साथ भ्रमित न हों।$1
और$2
क्वेरी स्ट्रिंग के अंदरUSING
. में दिए गए मानों को देखें खंड, इनपुट पैरामीटर के लिए नहीं। -
मैं
SELECT *
. में बदल जाता हूं जैसा कि आपको घोषित रिटर्न प्रकार से मेल खाने के लिए पूरी पंक्ति को वापस करना होगा। -
अंतिम लेकिन कम से कम नहीं:इस पर विचार करना सुनिश्चित करें कि घोषित कार्यों के बारे में मैनुअल का क्या कहना है
SECURITY DEFINER
।
रिटर्न प्रकार
यदि आप पूरी पंक्ति वापस नहीं करना चाहते हैं, तो एक सुविधाजनक संभावना है:
CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)
RETURNS TABLE (invoice_no varchar(125), amount numeric(12,2) AS ...
फिर आपको प्रत्येक कॉल के साथ एक कॉलम परिभाषा सूची प्रदान करने की आवश्यकता नहीं है और इसे सरल बनाया जा सकता है:
SELECT * FROM select_to_transactions3('invoice_no', '1103300105472', 1);