มันขึ้นอยู่กับสิ่งที่คุณต้องการที่จะทดสอบว่า
สคีมาข้อมูล?
ในการค้นหา "มีตารางอยู่หรือไม่ " ( ไม่ว่าใครจะขอ ) การสอบถาม schema ของข้อมูล ( information_schema.tables
) นั้นไม่ถูกต้องพูดอย่างเคร่งครัดเพราะ ( ต่อเอกสารประกอบ ):
เฉพาะตารางและมุมมองเหล่านั้นเท่านั้นที่แสดงว่าผู้ใช้ปัจจุบันมีสิทธิ์เข้าถึง (โดยเป็นเจ้าของหรือมีสิทธิ์บางอย่าง)
เคียวรีที่จัดเตรียมโดย @kongสามารถส่งคืนFALSE
ได้ แต่ตารางยังคงมีอยู่ มันตอบคำถาม:
วิธีตรวจสอบว่ามีตาราง (หรือมุมมอง) อยู่และผู้ใช้ปัจจุบันสามารถเข้าถึงได้หรือไม่
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
สคีมาข้อมูลมีประโยชน์เป็นหลักในการพกพาข้ามรุ่นหลักและข้าม RDBMS ที่แตกต่างกัน แต่การนำไปปฏิบัตินั้นช้าเพราะ Postgres ต้องใช้มุมมองที่ซับซ้อนเพื่อให้สอดคล้องกับมาตรฐาน ( information_schema.tables
เป็นตัวอย่างที่ค่อนข้างง่าย) และข้อมูลบางอย่าง (เช่น OIDs) ได้รับหายไปในการแปลจากแคตตาล็อกระบบ - ซึ่งจริง ๆ แล้วนำข้อมูลทั้งหมด
แคตตาล็อกระบบ
คำถามของคุณคือ:
จะตรวจสอบว่ามีตารางอยู่ได้อย่างไร
SELECT EXISTS (
SELECT FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
AND c.relkind = 'r' -- only tables
);
ใช้แคตตาล็อกระบบpg_class
และpg_namespace
โดยตรงซึ่งเร็วกว่ามากเช่นกัน อย่างไรก็ตามตามเอกสารเกี่ยวกับpg_class
:
แคpg_class
ตตาล็อกตารางแคตตาล็อกและทุกอย่างอื่น ๆ ที่มีคอลัมน์หรือเป็นอย่างอื่นคล้ายกับตาราง ซึ่งรวมถึงดัชนี (แต่เห็นด้วยpg_index
), ลำดับ , มุมมอง , มุมมองที่เป็นรูปธรรม , ประเภทประกอบและตาราง TOAST ;
สำหรับคำถามนี้โดยเฉพาะนอกจากนี้คุณยังสามารถใช้มุมมองระบบ pg_tables
เรียบง่ายขึ้นและพกพาได้มากกว่าในรุ่นหลัก ๆ ของ Postgres (ซึ่งแทบจะไม่ต้องกังวลกับแบบสอบถามพื้นฐานนี้):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
ตัวระบุต้องไม่ซ้ำกันในวัตถุทั้งหมดที่กล่าวถึงข้างต้น หากคุณต้องการถาม:
วิธีการตรวจสอบว่าชื่อสำหรับตารางหรือวัตถุที่คล้ายกันในสคีมาที่กำหนดจะถูกนำมาใช้?
SELECT EXISTS (
SELECT FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
);
ทางเลือก: cast to regclass
SELECT 'schema_name.table_name'::regclass
สิ่งนี้ทำให้เกิดข้อยกเว้นถ้าตาราง (ทางเลือกที่มีคุณสมบัติของสคีมา) (หรือวัตถุอื่น ๆ ที่ใช้ชื่อนั้น) ไม่มีอยู่
หากคุณไม่ได้กำหนดชื่อสคีมาให้เพี้ยนไปที่regclass
ค่าดีฟอลต์search_path
และและส่งคืน OID สำหรับตารางแรกที่พบ - หรือข้อยกเว้นถ้าตารางอยู่ในสกีมาที่ไม่มีอยู่ในรายการ หมายเหตุว่า schemas ระบบpg_catalog
และpg_temp
(schema สำหรับวัตถุชั่วคราวของเซสชั่นปัจจุบัน) search_path
เป็นส่วนหนึ่งของการทำงานโดยอัตโนมัติ
คุณสามารถใช้และจับข้อยกเว้นที่เป็นไปได้ในฟังก์ชั่น ตัวอย่าง:
ข้อความค้นหาด้านบนหลีกเลี่ยงข้อยกเว้นที่เป็นไปได้และเร็วขึ้นเล็กน้อย
ง่ายกว่ามากตอนนี้:
SELECT to_regclass('schema_name.table_name');
เหมือนกับนักแสดงแต่มันกลับมา ...
... ว่างเปล่าแทนที่จะทิ้งข้อผิดพลาดหากไม่พบชื่อ
[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]