संदर्भित कॉलम में 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 के साथ परीक्षण किया गया और मेरे लिए काम करता है।
मैं एक ही विदेशी कॉलम को एक क्वेरी में संदर्भित करने वाली कई तालिकाओं को समूहित करता हूं और एक सिंहावलोकन देने के लिए संदर्भित तालिकाओं की एक सूची जोड़ता हूं।