ฉันจะรับรายการฟังก์ชันทั้งหมดที่เก็บไว้ในฐานข้อมูลของสคีมาเฉพาะใน PostgreSQL ได้อย่างไร


138

ฉันต้องการเชื่อมต่อกับฐานข้อมูล PostgreSQL และค้นหาฟังก์ชันทั้งหมดสำหรับสคีมาเฉพาะ

ความคิดของฉันคือฉันสามารถค้นหา pg_catalog หรือ information_schema และรับรายการฟังก์ชันทั้งหมดได้ แต่ฉันไม่สามารถทราบได้ว่าชื่อและพารามิเตอร์ถูกเก็บไว้ที่ใด ฉันกำลังมองหาคำค้นหาที่จะให้ชื่อฟังก์ชันและประเภทพารามิเตอร์ที่ใช้ (และลำดับที่ใช้)

มีวิธีทำไหม?

คำตอบ:


195
\df <schema>.*

ในpsqlให้ข้อมูลที่จำเป็น

หากต้องการดูแบบสอบถามที่ใช้ภายในให้เชื่อมต่อกับฐานข้อมูลด้วยpsqlและระบุตัวเลือก" -E" (หรือ " --echo-hidden") เพิ่มเติมจากนั้นดำเนินการคำสั่งด้านบน


1
คุณช่วยวางข้อความค้นหานั้นได้ไหม
Rudd Zwolinski

3
เลือก n.nspname เป็น "Schema", p.proname เป็น "Name", pg_catalog.pg_get_function_result (p.oid) เป็น "Result data type", pg_catalog.pg_get_function_arguments (p.oid) เป็น "Argument data types", CASE WHEN p .proisagg แล้ว 'agg' เมื่อ p.proiswindow แล้ว 'window' WHEN p.prorettype = 'pg_catalog.trigger' :: pg_catalog.regtype แล้ว 'ทริกเกอร์' ELSE 'ปกติ' END เป็น "ประเภท" จาก pg_catalog.pg_proc p LEFT JOIN pg_catalog .pg_namespace n บน n.oid = p.pronamespace WHERE n.nspname ~ '^ (public) $' ORDER BY 1, 2, 4; ด้านบนคือข้อความค้นหาที่สร้างขึ้น (จาก \ set ECHO_HIDDEN 'on')
Simon D

92

หลังจากค้นหาฉันก็พบinformation_schema.routinesโต๊ะและinformation_schema.parametersโต๊ะ เมื่อใช้สิ่งเหล่านี้เราสามารถสร้างแบบสอบถามเพื่อจุดประสงค์นี้ LEFT JOIN แทนที่จะเป็น JOIN จำเป็นต้องดึงฟังก์ชันที่ไม่มีพารามิเตอร์

SELECT routines.routine_name, parameters.data_type, parameters.ordinal_position
FROM information_schema.routines
    LEFT JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
WHERE routines.specific_schema='my_specified_schema_name'
ORDER BY routines.routine_name, parameters.ordinal_position;

2
คุณจะพบว่าoidvectortypesมีประโยชน์มากเกินไป ดูคำตอบใหม่: stackoverflow.com/a/24034604/398670
Craig Ringer

โค้ดด้านบนจะไม่แสดงฟังก์ชันทั้งหมดคุณต้องใช้ LEFT JOIN แทน JOIN เพื่อแสดงฟังก์ชันที่ไม่มีพารามิเตอร์อินพุต
เดวิด

35

หากมีใครสนใจนี่คือสิ่งที่ดำเนินการค้นหาโดยpsqlpostgres 9.1:

SELECT n.nspname as "Schema",
  p.proname as "Name",
  pg_catalog.pg_get_function_result(p.oid) as "Result data type",
  pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
 CASE
  WHEN p.proisagg THEN 'agg'
  WHEN p.proiswindow THEN 'window'
  WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
  ELSE 'normal'
 END as "Type"
FROM pg_catalog.pg_proc p
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE pg_catalog.pg_function_is_visible(p.oid)
      AND n.nspname <> 'pg_catalog'
      AND n.nspname <> 'information_schema'
ORDER BY 1, 2, 4;

คุณสามารถรับสิ่งที่psqlรันสำหรับคำสั่งแบ็กสแลชได้โดยรันpsqlด้วย-Eแฟล็ก


เพิ่งเจอคำตอบของคุณและลองใช้แบบสอบถามใน Postgres 11.5 มันบอกว่า:ERROR: column p.proisagg does not exist
Christiaan Westerbeek

ขอบคุณสำหรับสิ่งนี้; สองคำตอบที่ได้รับการโหวตสูงสุดไม่ได้แสดงฟังก์ชันของฉัน!
machineghost

29

มีฟังก์ชั่นที่สะดวกoidvectortypesซึ่งทำให้ง่ายขึ้นมาก

SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes)) 
FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'my_namespace';

เครดิตสิงห์ Hsu และ Regina Obe ที่ Postgres ออนไลน์oidvectortypesสำหรับการชี้ออก ฉันเคยเขียนฟังก์ชันที่คล้ายกันมาก่อน แต่ใช้นิพจน์ซ้อนที่ซับซ้อนซึ่งฟังก์ชันนี้ไม่จำเป็นต้องใช้

ดูคำตอบที่เกี่ยวข้อง


(แก้ไขปี 2559)

การสรุปตัวเลือกรายงานทั่วไป:

-- Compact:
SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes))

-- With result data type: 
SELECT format(
       '%I.%I(%s)=%s', 
       ns.nspname, p.proname, oidvectortypes(p.proargtypes),
       pg_get_function_result(p.oid)
)

-- With complete argument description: 
SELECT format('%I.%I(%s)', ns.nspname, p.proname, pg_get_function_arguments(p.oid))

-- ... and mixing it.

-- All with the same FROM clause:
FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'my_namespace';

ข้อสังเกต : ใช้p.proname||'_'||p.oid AS specific_name เพื่อรับชื่อที่ไม่ซ้ำกันหรือเข้าร่วมกับinformation_schemaตาราง - ดูroutinesและparametersที่คำตอบของ @ RuddZwolinski


OIDของฟังก์ชัน (ดู  pg_catalog.pg_proc) และชื่อเฉพาะของฟังก์ชัน(ดู  information_schema.routines) เป็นตัวเลือกอ้างอิงหลักของฟังก์ชัน ด้านล่างนี้เป็นฟังก์ชันที่มีประโยชน์ในการรายงานและบริบทอื่น ๆ

--- --- --- --- ---
--- Useful overloads: 

CREATE FUNCTION oidvectortypes(p_oid int) RETURNS text AS $$
    SELECT oidvectortypes(proargtypes) FROM pg_proc WHERE oid=$1;
$$ LANGUAGE SQL IMMUTABLE;

CREATE FUNCTION oidvectortypes(p_specific_name text) RETURNS text AS $$
    -- Extract OID from specific_name and use it in oidvectortypes(oid).
    SELECT oidvectortypes(proargtypes) 
    FROM pg_proc WHERE oid=regexp_replace($1, '^.+?([^_]+)$', '\1')::int;
$$ LANGUAGE SQL IMMUTABLE;

CREATE FUNCTION pg_get_function_arguments(p_specific_name text) RETURNS text AS $$
    -- Extract OID from specific_name and use it in pg_get_function_arguments.
    SELECT pg_get_function_arguments(regexp_replace($1, '^.+?([^_]+)$', '\1')::int)
$$ LANGUAGE SQL IMMUTABLE;

--- --- --- --- ---
--- User customization: 

CREATE FUNCTION pg_get_function_arguments2(p_specific_name text) RETURNS text AS $$
    -- Example of "special layout" version.
    SELECT trim(array_agg( op||'-'||dt )::text,'{}') 
    FROM (
        SELECT data_type::text as dt, ordinal_position as op
        FROM information_schema.parameters 
        WHERE specific_name = p_specific_name 
        ORDER BY ordinal_position
    ) t
$$ LANGUAGE SQL IMMUTABLE;

pronameเป็นชื่อ แต่วิธีการที่จะได้รับ OID สำหรับเช่น ใช้ในpg_catalog.pg_get_function_result(oid))?
Peter Krauss

1
@PeterKrauss oidคอลัมน์ของpg_proc. มันเป็นคอลัมน์ที่ซ่อนอยู่
Craig Ringer

1
โปรดดูstackoverflow.com/a/25388031/161040สำหรับวิธีการแยกฟังก์ชันที่ขึ้นกับส่วนขยาย (เช่นฟังก์ชันจาก PostGIS)
Simon D

20

เรียกใช้แบบสอบถาม SQL ด้านล่างเพื่อสร้างมุมมองซึ่งจะแสดงฟังก์ชันทั้งหมด:

CREATE OR REPLACE VIEW show_functions AS
    SELECT routine_name FROM information_schema.routines 
        WHERE routine_type='FUNCTION' AND specific_schema='public';

10

เป็นความคิดที่ดีที่ตั้งชื่อฟังก์ชั่นที่มีนามแฝง commun ในคำแรกสำหรับกรองชื่อด้วยLIKE ตัวอย่างด้วยสคีมาสาธารณะใน Postgresql 9.4 โปรดแทนที่ด้วยโครงร่างของเขา

SELECT routine_name 
FROM information_schema.routines 
WHERE routine_type='FUNCTION' 
  AND specific_schema='public'
  AND routine_name LIKE 'aliasmyfunctions%';

5

ตัวอย่าง:

perfdb-# \df information_schema.*;

List of functions
        Schema      |        Name        | Result data type | Argument data types |  Type  
 information_schema | _pg_char_max_length   | integer | typid oid, typmod integer | normal
 information_schema | _pg_char_octet_length | integer | typid oid, typmod integer | normal
 information_schema | _pg_datetime_precision| integer | typid oid, typmod integer | normal
 .....
 information_schema | _pg_numeric_scale     | integer | typid oid, typmod integer | normal
 information_schema | _pg_truetypid         | oid     | pg_attribute, pg_type     | normal
 information_schema | _pg_truetypmod        | integer | pg_attribute, pg_type     | normal
(11 rows)

5
คำตอบของ Milen แตกต่างกันอย่างไร
a_horse_with_no_name

3
นี่ไม่ใช่คิวรี แต่เป็นคำสั่งของpsqlอินเทอร์เฟซไคลเอ็นต์ Postgres สิ่งนี้จะใช้ได้เฉพาะในpsqlและไม่ใช่แบบสอบถาม SQL ในทางเทคนิค
GregT

4

รับรายชื่อ function_schema และ function_name ...


SELECT
    n.nspname AS function_schema,
    p.proname AS function_name
FROM
    pg_proc p
    LEFT JOIN pg_namespace n ON p.pronamespace = n.oid
WHERE
    n.nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY
    function_schema,
    function_name;

2

ฟังก์ชันนี้ส่งคืนรูทีนที่ผู้ใช้กำหนดทั้งหมดในฐานข้อมูลปัจจุบัน

SELECT pg_get_functiondef(p.oid) FROM pg_proc p
INNER JOIN pg_namespace ns ON p.pronamespace = ns.oid
WHERE ns.nspname = 'public';
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.