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

मैं टेबल कैसे ढूंढ सकता हूं जो किसी विदेशी कुंजी के माध्यम से किसी विशेष पंक्ति का संदर्भ देता है?

संदर्भित कॉलम में NULL मान

यह क्वेरी सभी पंक्तियों को खोजने के लिए DML स्टेटमेंट तैयार करती है सभी तालिकाओं में, जहां एक स्तंभ में एक विदेशी-कुंजी बाधा होती है किसी अन्य तालिका को संदर्भित करना लेकिन एक NULL रखें उस कॉलम में मान:

WITH x AS (
 SELECT c.conrelid::regclass    AS tbl
      , c.confrelid::regclass   AS ftbl
      , quote_ident(k.attname)  AS fk
      , quote_ident(pf.attname) AS pk
 FROM   pg_constraint c
 JOIN   pg_attribute  k ON (k.attrelid, k.attnum) = (c.conrelid, c.conkey[1])
 JOIN   pg_attribute  f ON (f.attrelid, f.attnum) = (c.confrelid, c.confkey[1])
 LEFT   JOIN pg_constraint p  ON p.conrelid = c.conrelid AND p.contype = 'p'
 LEFT   JOIN pg_attribute  pf ON (pf.attrelid, pf.attnum)
                               = (p.conrelid, p.conkey[1])
 WHERE  c.contype   = 'f'
 AND    c.confrelid = 'fk_tbl'::regclass  -- references to this tbl
 AND    f.attname   = 'fk_tbl_id'         -- and only to this column
)
SELECT string_agg(format(
'SELECT %L AS tbl
     , %L AS pk
     , %s::text AS pk_val
     , %L AS fk
     , %L AS ftbl
FROM   %1$s WHERE %4$s IS NULL'
                  , tbl
                  , COALESCE(pk 'NONE')
                  , COALESCE(pk 'NULL')
                  , fk
                  , ftbl), '
UNION ALL
') || ';'
FROM   x;

इस तरह की एक क्वेरी तैयार करता है:

SELECT 'some_tbl' AS tbl
     , 'some_tbl_id' AS pk
     , some_tbl_id::text AS pk_val
     , 'fk_tbl_id' AS fk
     , 'fk_tbl' AS ftbl
FROM   some_tbl WHERE fk_tbl_id IS NULL
UNION ALL
SELECT 'other_tbl' AS tbl
     , 'other_tbl_id' AS pk
     , other_tbl_id::text AS pk_val
     , 'some_name_id' AS fk
     , 'fk_tbl' AS ftbl
FROM   other_tbl WHERE some_name_id IS NULL;

इस तरह उत्पादन करता है:

    tbl    |     pk       | pk_val |    fk        |  ftbl
-----------+--------------+--------+--------------+--------
 some_tbl  | some_tbl_id  | 49     | fk_tbl_id    | fk_tbl
 some_tbl  | some_tbl_id  | 58     | fk_tbl_id    | fk_tbl
 other_tbl | other_tbl_id | 66     | some_name_id | fk_tbl
 other_tbl | other_tbl_id | 67     | some_name_id | fk_tbl
  • बहु-स्तंभ विदेशी या प्राथमिक कुंजियों को मज़बूती से कवर नहीं करता . इसके लिए आपको क्वेरी को और अधिक जटिल बनाना होगा।

  • मैंने सभी प्राथमिक कुंजी मानों . डाली हैं करने के लिए text सभी प्रकार को कवर करने के लिए।

  • किसी अन्य या किसी . की ओर इशारा करते हुए विदेशी कुंजी खोजने के लिए इन पंक्तियों को अपनाएं या हटाएं कॉलम / टेबल:

    AND    c.confrelid = 'fk_tbl'::regclass
    AND    f.attname = 'fk_tbl_id' -- and only this column
    
  • PostgreSQL 9.1.4 के साथ परीक्षण किया गया। मैं pg_catalog . का उपयोग करता हूं टेबल। वास्तव में मैं यहां जो कुछ भी उपयोग करता हूं, उसमें से कुछ भी बदलने वाला नहीं है, लेकिन प्रमुख रिलीज में इसकी गारंटी नहीं है। information_schema . से तालिकाओं के साथ इसे फिर से लिखें यदि आपको अद्यतनों में मज़बूती से काम करने के लिए इसकी आवश्यकता है। यह धीमा है, लेकिन निश्चित है।

  • मैंने जेनरेट की गई डीएमएल स्क्रिप्ट में टेबल नामों को साफ नहीं किया, क्योंकि quote_ident() स्कीमा-योग्य नामों के साथ विफल हो जाएगा। हानिकारक तालिका नामों जैसे "users; DELETE * FROM users;" से बचना आपकी जिम्मेदारी है . कुछ और प्रयासों से, आप स्कीमा-नाम और तालिका नाम को अलग-अलग प्राप्त कर सकते हैं और quote_ident() का उपयोग कर सकते हैं ।

संदर्भित कॉलम में NULL मान

मेरा पहला समाधान आपके द्वारा पूछे जाने वाले से कुछ अलग करता है, क्योंकि आप जो वर्णन करते हैं (जैसा कि मैं इसे समझता हूं) अस्तित्वहीन है। मान NULL "अज्ञात" है और इसे संदर्भित नहीं किया जा सकता है। यदि आप वास्तव में NULL वाली पंक्तियों को खोजना चाहते हैं एक कॉलम में मान जिसमें FK बाधाएं को . की ओर इशारा करती हैं यह (NULL . के साथ विशेष पंक्ति में नहीं मूल्य, निश्चित रूप से), तो क्वेरी को बहुत सरल बनाया जा सकता है:

WITH x AS (
 SELECT c.confrelid::regclass   AS ftbl
       ,quote_ident(f.attname)  AS fk
       ,quote_ident(pf.attname) AS pk
       ,string_agg(c.conrelid::regclass::text, ', ') AS referencing_tbls
 FROM   pg_constraint c
 JOIN   pg_attribute  f ON (f.attrelid, f.attnum) = (c.confrelid, c.confkey[1])
 LEFT   JOIN pg_constraint p  ON p.conrelid = c.confrelid AND p.contype = 'p'
 LEFT   JOIN pg_attribute  pf ON (pf.attrelid, pf.attnum)
                               = (p.conrelid, p.conkey[1])
 WHERE  c.contype = 'f'
 -- AND    c.confrelid = 'fk_tbl'::regclass  -- only referring this tbl
 GROUP  BY 1, 2, 3
)
SELECT string_agg(format(
'SELECT %L AS ftbl
     , %L AS pk
     , %s::text AS pk_val
     , %L AS fk
     , %L AS referencing_tbls
FROM   %1$s WHERE %4$s IS NULL'
                  , ftbl
                  , COALESCE(pk, 'NONE')
                  , COALESCE(pk, 'NULL')
                  , fk
                  , referencing_tbls), '
UNION ALL
') || ';'
FROM   x;

संपूर्ण डेटाबेस में ऐसी सभी पंक्तियों को ढूँढता है (एक तालिका पर प्रतिबंध पर टिप्पणी की)। पोस्टग्रेज 9.1.4 के साथ परीक्षण किया गया और मेरे लिए काम करता है।

मैं एक ही विदेशी कॉलम को एक क्वेरी में संदर्भित करने वाली कई तालिकाओं को समूहित करता हूं और एक सिंहावलोकन देने के लिए संदर्भित तालिकाओं की एक सूची जोड़ता हूं।



  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. लगातार दोहराव/डुप्लिकेट की संख्या का आदेश दिया

  3. संबंधित अनुक्रम को हटाए बिना PostgreSQL में एक तालिका को हटाना

  4. VPS/समर्पित सर्वर पर PostgreSQL कैसे प्राप्त करें

  5. क्या पोस्टग्रेस्क्ल के लिए डेटा विज़ुअलाइज़ेशन टूल है जो इंटर स्कीमा संबंधों को भी प्रदर्शित करने में सक्षम है?