मुझे पिछली बार याद नहीं आया कि मुझे वास्तव में plpgsql में लूपिंग के लिए एक स्पष्ट कर्सर का उपयोग करने की आवश्यकता थी।FOR
के निहित कर्सर का उपयोग करें लूप, यह ज्यादा साफ है:
DO
$$
DECLARE
rec record;
nbrow bigint;
BEGIN
FOR rec IN
SELECT *
FROM pg_tables
WHERE tablename NOT LIKE 'pg\_%'
ORDER BY tablename
LOOP
EXECUTE 'SELECT count(*) FROM '
|| quote_ident(rec.schemaname) || '.'
|| quote_ident(rec.tablename)
INTO nbrow;
-- Do something with nbrow
END LOOP;
END
$$;
सभी स्कीमाओं के लिए यह कार्य करने के लिए आपको स्कीमा नाम शामिल करना होगा (उन स्कीमाओं सहित जो आपके search_path
में नहीं हैं) )।
साथ ही, आपको वास्तव में जरूरत . है quote_ident()
use का इस्तेमाल करने के लिए या format()
%I
. के साथ या एक regclass
एसक्यूएल इंजेक्शन के खिलाफ सुरक्षा के लिए चर। तालिका का नाम लगभग कुछ भी हो सकता है दोहरे उद्धरण चिह्नों के अंदर। देखें:
- तालिका नाम PostgreSQL फ़ंक्शन पैरामीटर के रूप में
मामूली विवरण:अंडरस्कोर से बचें (_
) LIKE
. में इसे शाब्दिक . बनाने के लिए पैटर्न अंडरस्कोर:tablename NOT LIKE 'pg\_%'
मैं यह कैसे कर सकता हूं:
DO
$$
DECLARE
tbl regclass;
nbrow bigint;
BEGIN
FOR tbl IN
SELECT c.oid
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
AND n.nspname NOT LIKE 'pg\_%' -- system schema(s)
AND n.nspname <> 'information_schema' -- information schema
ORDER BY n.nspname, c.relname
LOOP
EXECUTE 'SELECT count(*) FROM ' || tbl INTO nbrow;
-- raise notice '%: % rows', tbl, nbrow;
END LOOP;
END
$$;
क्वेरी pg_catalog.pg_class
tablename
. के बजाय , यह तालिका का OID प्रदान करता है।
वस्तु पहचानकर्ता प्रकार regclass
सरल बनाना आसान है। n विशेष रूप से, तालिका नाम डबल-उद्धृत और स्कीमा-योग्य होते हैं जहां आवश्यक स्वचालित रूप से (एसक्यूएल इंजेक्शन को भी रोकता है)।
इस क्वेरी में अस्थायी तालिकाओं को भी शामिल नहीं किया गया है (अस्थायी स्कीमा का नाम pg_temp%
है आंतरिक रूप से)।
किसी दिए गए स्कीमा से केवल तालिकाएँ शामिल करने के लिए:
AND n.nspname = 'public' -- schema name here, case-sensitive