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

PostgreSQL में एक रिकॉर्ड चर के लिए गतिशील रूप से कॉलम नाम पास करना

इस डमी टेबल के साथ काम करना

CREATE TEMP TABLE foo (id int, my_num numeric);
INSERT INTO foo VALUES (1, 12.34)

सबसे पहले, मैंने आपके उदाहरण को सरल और स्वच्छ किया:

  • कुछ शोर हटा दिया जो प्रश्न के लिए अप्रासंगिक है।

  • RETURNS SETOF void शायद ही समझ में आता है। मैं RETURNS void का उपयोग करता हूं इसके बजाय।

  • मैं text का उपयोग करता हूं इसके बजाय character varying , केवल सादगी के लिए।

  • डायनेमिक SQL का उपयोग करते समय, आपके पास है SQL इंजेक्शन से बचाव के लिए, मैं format() . का उपयोग करता हूँ %I . के साथ इस मामले में। और भी तरीके हैं।

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

मूल कार्य

CREATE OR REPLACE FUNCTION getrowdata1(table_name text, id int)
  RETURNS void AS
$func$ 
DECLARE
   srowdata record;
   reqfield text := 'my_num';   -- assigning at declaration time for convenience
   value    numeric;
BEGIN

RAISE NOTICE 'id: %', id; 

EXECUTE format('SELECT * FROM %I WHERE id = $1', table_name)
USING  id
INTO   srowdata;

RAISE NOTICE 'srowdata: %', srowdata;

RAISE NOTICE 'srowdatadata.my_num: %', srowdata.my_num;

/* This does not work, even with dynamic SQL
EXECUTE format('SELECT ($1).%I', reqfield)
USING srowdata
INTO value;

RAISE NOTICE 'value: %', value;
*/

END
$func$ LANGUAGE plpgsql;

कॉल करें:

SELECT * from getrowdata1('foo', 1);

टिप्पणी वाला हिस्सा एक अपवाद उठाएगा:

<ब्लॉककोट>

रिकॉर्ड डेटा प्रकार में कॉलम "my_num" की पहचान नहीं कर सका:सेलेक्ट * fromgetrowdata(1,'foo')

hstore

आपको अतिरिक्त मॉड्यूल hstore install स्थापित करने की आवश्यकता है इसके लिए। एक बार प्रति डेटाबेस के साथ:

CREATE EXTENSION hstore;

तब सब कुछ इस तरह काम कर सकता था:

CREATE OR REPLACE FUNCTION getrowdata2(table_name text, id int)
  RETURNS void AS
$func$ 
DECLARE
   hstoredata hstore;
   reqfield   text := 'my_num';
   value      numeric;
BEGIN

RAISE NOTICE 'id: %', id; 

EXECUTE format('SELECT hstore(t) FROM %I t WHERE id = $1', table_name)
USING  id
INTO   hstoredata;

RAISE NOTICE 'hstoredata: %', hstoredata;

RAISE NOTICE 'hstoredata.my_num: %', hstoredata -> 'my_num';

value := hstoredata -> reqfield;

RAISE NOTICE 'value: %', value;

END
$func$ LANGUAGE plpgsql;

कॉल करें:

SELECT * from getrowdata2('foo', 1);

बहुरूपी प्रकार

अतिरिक्त मॉड्यूल स्थापित किए बिना वैकल्पिक।

चूंकि आप अपने रिकॉर्ड चर में एक पूरी पंक्ति का चयन करते हैं, इसलिए एक अच्छी तरह से परिभाषित प्रकार . होता है इसके लिए प्रति परिभाषा। इसका इस्तेमाल करें। कुंजी शब्द है बहुरूपी प्रकार

CREATE OR REPLACE FUNCTION getrowdata3(_tbl anyelement, id int)
  RETURNS void AS
$func$ 
DECLARE
   reqfield text := 'my_num';
   value    numeric;
BEGIN

RAISE NOTICE 'id: %', id; 

EXECUTE format('SELECT * FROM %s WHERE id = $1', pg_typeof(_tbl))
USING  id
INTO   _tbl;

RAISE NOTICE '_tbl: %', _tbl;

RAISE NOTICE '_tbl.my_num: %', _tbl.my_num;

EXECUTE 'SELECT ($1).' || reqfield   -- requfield must be SQLi-safe or escape
USING _tbl
INTO  value;

RAISE NOTICE 'value: %', value;

END
$func$ LANGUAGE plpgsql;

कॉल करें:

SELECT * from getrowdata3(NULL::foo, 1);

-> SQLfiddle

  • मैं (ab-)इनपुट पैरामीटर _tbl . का उपयोग करता हूं तीन . के लिए यहाँ उद्देश्य:

    • अच्छी तरह से परिभाषित प्रकार प्रदान करता है रिकॉर्ड के
    • नाम प्रदान करता है तालिका के, स्वचालित रूप से स्कीमा-योग्य
    • चर के रूप में कार्य करता है।
  • इस संबंधित उत्तर में अधिक स्पष्टीकरण (अंतिम अध्याय):
    विभिन्न चयन प्रश्नों के आउटपुट को वापस करने के लिए एक PL/pgSQL फ़ंक्शन को रिफैक्टर करें




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. तालिका Grupo Cakephp के लिए FROM-क्लॉज प्रविष्टि गुम है

  2. एकल पैरामीटर में एकाधिक मान पास करें

  3. psql - कमांड के परिणामों को एक फाइल में सेव करें

  4. समानांतर में कई सरणियों को खोलना

  5. PostgreSQL प्रतिकृति सर्वोत्तम अभ्यास - भाग 1