แบบสอบถามเพื่อส่งกลับชื่อคอลัมน์ผลลัพธ์และชนิดข้อมูลของแบบสอบถามตารางหรือมุมมอง


21

มีแบบสอบถามหรือคำสั่ง PostgreSQL ที่ส่งคืนชื่อเขตข้อมูลและชนิดเขตข้อมูลของแบบสอบถามตารางหรือมุมมองหรือไม่

เช่นวิธีแก้ปัญหาหากนำไปใช้กับแบบสอบถาม SELECT อย่างง่ายเช่นSELECT * from personควรส่งคืนรายการเช่น:

Column Name   | Column Type
===========================
First Name    | character
Last Name     | character
Age           | integer
Date of Birth | date

ฉันค้นหาinformation_schemaมุมมองที่อธิบายไว้ในคำตอบด้านล่างและดูเหมือนว่าจะครอบคลุมตารางค่อนข้างดีและฉันคิดว่ามันครอบคลุมมุมมองเช่นกัน แต่ฉันยังไม่ได้ตรวจสอบ

สุดท้ายเป็นข้อ ๆ แต่ที่ถูกต้องเช่นแบบสอบถาม SELECT เกี่ยวข้องกับJOINS, UNIONSฯลฯ ในฐานข้อมูล มีขั้นตอนในตัวหรือโพรซีเดอร์หรือสคริปต์อื่นที่เก็บไว้ซึ่งสามารถส่งคืนค่าเดียวกันสำหรับ QUERY ที่ถูกต้องได้หรือไม่?

ฉันกำลังพัฒนาโปรแกรมที่สร้างข้อมูลและแบบฟอร์มการสืบค้นและต้องการข้อมูลสำหรับการตรวจสอบความถูกต้องของข้อมูลและการใช้งานฟังก์ชันในข้อมูลที่ส่งคืน


เห็นได้ชัดว่าไม่มีคำสั่ง "เดียว" แต่มีหลายวิธีในการดึงข้อมูลจากแคตตาล็อกระบบ โปรดถามคำถามเฉพาะเพิ่มตัวอย่างและสิ่งที่คุณคาดหวังจากผลตอบแทนและให้แนวคิดเกี่ยวกับความตั้งใจที่อยู่เบื้องหลัง
Erwin Brandstetter

1
เหตุผลของความเรียบง่ายก็คือเท่าที่ลูกค้ามีความกังวลแบบสอบถามเช่นSELECTแบบสอบถามที่ไม่ใช่ข้อมูลที่กำหนดหรือแบบสอบถามการจัดการข้อมูลไม่ว่าจะเป็นในตารางมุมมองหรือแบบสอบถามอื่น ๆ กลับแถวและคอลัมน์ของข้อมูลดังนั้น PostgreSQL ควรจะกลับ รายการชื่อคอลัมน์และประเภทข้อมูล information_schemaมุมมองที่ระบุไว้ด้านล่างในคำตอบที่ดูเหมือนจะตอบมันสำหรับตารางและมุมมอง ข้อความค้นหา SELECT โดยพลการเป็นพรมแดนสุดท้าย ฉันจะแก้ไขคำตอบเพื่ออธิบายให้ดียิ่งขึ้น
vfclists

คำตอบ:


22

สกีมาสารสนเทศเทียบกับแคตตาล็อกระบบ

เรามีการพูดคุยกันหลายครั้ง สคีมาข้อมูลมีวัตถุประสงค์บางอย่าง ถ้าคุณรู้ทางของคุณไปรอบ ๆ แคตตาล็อกระบบเหล่านั้นจะให้บริการตามวัตถุประสงค์ที่ดีที่สุดIMO แคตตาล็อกระบบเป็นแหล่งข้อมูลจริงทั้งหมด

สคีข้อมูลให้มุมมองที่ความช่วยเหลือเกี่ยวกับการพกพาส่วนใหญ่ข้ามรุ่น Postgres ที่สำคัญเนื่องจากพกพาข้ามแพลตฟอร์ม RDBMS ที่แตกต่างกันมักจะเป็นภาพลวงตาครั้งเดียวคำสั่งของคุณมีมากพอที่จะมีความซับซ้อนจำเป็นที่จะต้องขึ้นไปดูแคตตาล็อกระบบมาตรฐาน และที่สำคัญที่สุดคือOracle ยังไม่รองรับโครงสร้างข้อมูล

มุมมองในสคีมาข้อมูลต้องข้ามหลายห่วงเพื่อให้ได้รูปแบบที่สอดคล้องกับมาตรฐาน ทำให้ช้าบางครั้งช้ามาก เปรียบเทียบแผนและประสิทธิภาพสำหรับวัตถุพื้นฐานเหล่านี้:

EXPLAIN ANALYZE SELECT * from information_schema.columns;
EXPLAIN ANALYZE SELECT * from pg_catalog.pg_attribute;

ความแตกต่างที่น่าทึ่ง มันขึ้นอยู่กับสิ่งที่คุณกำลังมองหา

ตัวอย่างของคุณ

สำหรับตัวอย่างของคุณSELECT * from tblให้เปรียบเทียบทั้งสองเคียวรีด้านล่างสำหรับตารางอย่างง่ายนี้:

CREATE TEMP TABLE foo(
   A numeric(12,3)
 , b timestamp(0)
);

การใช้pg_attribute:

SELECT attname, format_type(atttypid, atttypmod) AS type
FROM   pg_attribute
WHERE  attrelid = 'foo'::regclass
AND    attnum > 0
AND    NOT attisdropped
ORDER  BY attnum;

format_type() ส่งคืนชนิดที่สมบูรณ์พร้อมกับตัวดัดแปลงทั้งหมด:

attname | type
--------+-------------------------------
a       | numeric(12,3)
b       | timestamp(0) without time zone

นอกจากนี้ทราบว่านักแสดงที่จะแก้ไขชื่อตารางค่อนข้างชาญฉลาดตามปัจจุบันregclass search_pathนอกจากนี้ยังเพิ่มข้อยกเว้นหากชื่อไม่ถูกต้อง รายละเอียด:

การใช้information_schema.columns:

SELECT column_name, data_type
FROM   information_schema.columns
WHERE  table_name = 'foo'
ORDER  BY ordinal_position;

ข้อมูลมีมาตรฐาน แต่ไม่สมบูรณ์ :

column_name | data_type
------------+----------------------------
a           | numeric
b           | timestamp without time zone

ในการรับข้อมูลทั้งหมดสำหรับประเภทข้อมูลคุณต้องพิจารณาคอลัมน์เหล่านี้ทั้งหมดเพิ่มเติม:

character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision

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

รายการข้อดี & ข้อเสียข้อดีที่ใหญ่ที่สุด (IMO) เป็นตัวหนา:

มุมมองสคีมาข้อมูล

  • มักจะง่ายกว่า (ขึ้นอยู่กับ)
  • ช้า
  • ประมวลผลล่วงหน้าซึ่งอาจหรืออาจไม่เหมาะสมกับความต้องการของคุณ
  • selective (ผู้ใช้เห็นเฉพาะวัตถุที่มีสิทธิ์)
  • สอดคล้องกับมาตรฐาน SQL (ที่นำมาใช้โดย RDBMS หลักบางส่วน)
  • ส่วนใหญ่พกพาข้ามรุ่น Postgres หลัก
  • ไม่ต้องการความรู้เฉพาะเกี่ยวกับ Postgres
  • ตัวระบุมีความหมายยาวและบางครั้งก็น่าอึดอัดใจ

แคตตาล็อกระบบ

  • มักจะซับซ้อนมากขึ้น (ขึ้นอยู่กับ) ใกล้แหล่งที่มา
  • รวดเร็ว
  • สมบูรณ์ (คอลัมน์ระบบเหมือนoidรวมอยู่)
  • ไม่ปฏิบัติตามมาตรฐาน SQL
  • พกพาได้น้อยลงในเวอร์ชันหลักของ Postgres (แต่พื้นฐานจะไม่เปลี่ยนแปลง)
  • ต้องการความรู้เฉพาะเพิ่มเติมเกี่ยวกับ Postgres
  • ตัวบ่งชี้สั้นกระชับบรรยายสั้น แต่สะดวก

แบบสอบถามโดยพลการ

ในการรับรายการชื่อคอลัมน์และชนิดเดียวกันจากแบบสอบถามคุณสามารถใช้เคล็ดลับง่ายๆ: สร้างตารางชั่วคราวจากผลลัพธ์แบบสอบถามจากนั้นใช้เทคนิคเดียวกับข้างต้น

คุณสามารถผนวกLIMIT 0เนื่องจากคุณไม่ต้องการข้อมูลจริง:

CREATE TEMP TABLE tmp123 AS
SELECT 1::numeric, now()
LIMIT  0;

ในการรับชนิดข้อมูลของแต่ละคอลัมน์คุณสามารถใช้ฟังก์ชันpg_typeof():

SELECT pg_typeof(1);

ขอบคุณมาก. ฉันได้ดูวิธีรับประเภทข้อมูลของคอลัมน์ใน pg_attribute นาน ๆ มาและเพิ่งเจอโพสต์นี้ ขอบคุณโพสต์ของคุณ
Melinda

สิ่งนี้มีประโยชน์โดยทั่วไป แต่ไม่ตอบคำถามดั้งเดิมเกี่ยวกับวิธีรับข้อมูลเกี่ยวกับชนิดข้อมูลของคอลัมน์ที่คำสั่ง SELECT ส่งมอบ มันไม่ได้เกี่ยวกับคอลัมน์ของมุมมองหรือตารางซึ่งแน่นอนอยู่ในแคตตาล็อกระบบและจะแสดงในสคีมาข้อมูลเช่นกัน
Holger Jakobs

2

คุณสามารถใช้psqlไคลเอนต์บรรทัดคำสั่ง

\dt จะแสดงรายการของตาราง

\dv จะแสดงรายการมุมมอง

\d [object_name] จะอธิบายสคีมาของตารางหรือมุมมอง

ไม่แน่ใจว่าคุณจะอธิบายคำค้นหาได้อย่างไร

ข้อมูลเพิ่มเติม: https://manikandanmv.wordpress.com/tag/basic-psql-commands/


2

หากคุณเข้าถึง pg_catalog และใช้ PgAdmin3 ฉันขอแนะนำวิธีแก้ปัญหาที่ฉันพบในบล็อก Valentine Tech ( http://tech.valgog.com/2011/02/pgadmin-iii-macros-get-table-fields) html ) เป็นมาโคร PgAdmin3 ที่สามารถเข้าถึงได้ด้วยช็อตคัตเพื่อแสดงคำจำกัดความของชื่อตารางที่เลือก

select quote_ident(nspname) || '.' || quote_ident(relname) as table_name, 
       quote_ident(attname) as field_name, 
       format_type(atttypid,atttypmod) as field_type, 
       case when attnotnull then ' NOT NULL' else '' end as null_constraint,
       case when atthasdef then 'DEFAULT ' || 
                                ( select pg_get_expr(adbin, attrelid) 
                                    from pg_attrdef 
                                   where adrelid = attrelid and adnum = attnum )::text else ''
       end as dafault_value,
       case when nullif(confrelid, 0) is not null
            then confrelid::regclass::text || '( ' || 
                 array_to_string( ARRAY( select quote_ident( fa.attname ) 
                                           from pg_attribute as fa 
                                          where fa.attnum = ANY ( confkey ) 
                                            and fa.attrelid = confrelid
                                          order by fa.attnum 
                                        ), ','
                                 ) || ' )'
            else '' end as references_to
  from pg_attribute 
       left outer join pg_constraint on conrelid = attrelid 
                                    and attnum = conkey[1] 
                                    and array_upper( conkey, 1 ) = 1,
       pg_class, 
       pg_namespace
 where pg_class.oid = attrelid
   and pg_namespace.oid = relnamespace
   and pg_class.oid = btrim( '$SELECTION$' )::regclass::oid
   and attnum > 0
   and not attisdropped
 order by attrelid, attnum;

ทำงานเหมือนจับใจและมีประโยชน์อย่างยิ่ง


1

ใช้มุมมองที่พวกเขากำลัง SQL มาตรฐานและมีข้อมูลที่คุณต้องการinformation_schema

คุณยังสามารถเข้าถึงได้โดยตรงpg_class, pg_attributeฯลฯ แต่ที่ unportable และมักจะ fiddlier; คุณอาจจะต้องฟังก์ชั่นผู้ช่วยเหมือนoidvectortypes , pg_get_function_argumentsฯลฯ สำหรับบางสิ่งบางอย่าง

หากคุณต้องการดูวิธีการpsqlดำเนินการสิ่งที่ชอบ\dtให้เรียกใช้psql -E- มันจะพิมพ์แบบสอบถาม อย่างไรก็ตามโดยปกติจะดีกว่าinformation_schemaหากใช้ถ้ามันจะตอบสนองความต้องการของคุณ


1

นี่อาจง่ายเกินไป แต่ pgAdmin4 แสดงประเภทฟิลด์ในผลลัพธ์ผลลัพธ์ โซลูชันอื่นข้างต้นอาจดูสง่างามกว่า แต่เมื่อฉันต้องการคำตอบอย่างรวดเร็วฉันพบว่า GUI แบบสอบถามของ pgAdmin4 นั้นใช้งานได้ดี การพยายามคิดหาชนิดของเขตข้อมูลของเขตข้อมูลจากการคำนวณที่ส่งคืนโดยมุมมองหรือฟังก์ชันอาจเป็นเรื่องยุ่งยาก

ป้อนคำอธิบายรูปภาพที่นี่


มันเป็นเรื่องดีมากที่ไม่ pgAdmin4 นี้ แต่วิธีการที่ไม่ได้ไปได้หรือไม่ เราสามารถค้นหาได้โดยไม่ต้องสแกนผ่านซอร์สโค้ดทั้งหมดของ PgAdmin4 หรือไม่?
Holger Jakobs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.