প্রদত্ত স্কিমে কোনও সারণী বিদ্যমান কিনা তা কীভাবে পরীক্ষা করবেন


149

পোস্টগ্রিজ 8.4 এবং বৃহত্তর ডাটাবেসে publicস্কিমাতে সাধারণ সারণী এবং স্কিমাতে কোম্পানির নির্দিষ্ট সারণী রয়েছে company
companyস্কিমা নাম সর্বদা শুরু হয়'company' এবং সংস্থার নম্বর দিয়ে শেষ হয়।
সুতরাং এখানে স্কিমা থাকতে পারে:

public
company1
company2
company3
...
companynn

একটি অ্যাপ্লিকেশন সর্বদা একটি একক সংস্থার সাথে কাজ করে।
দ্যsearch_pathODBC বা npgsql সংযোগ স্ট্রিং মত, মধ্যে সেই অনুযায়ী নিদিষ্ট হয়:

search_path='company3,public'

নির্দিষ্ট companynস্কিমে কোনও প্রদত্ত টেবিল উপস্থিত রয়েছে কিনা তা আপনি কীভাবে পরীক্ষা করবেন ?

উদাহরণ:

select isSpecific('company3','tablenotincompany3schema')

ফিরে আসা উচিত false, এবং

select isSpecific('company3','tableincompany3schema')

ফিরে আসা উচিত true

যে কোনও ক্ষেত্রে, ফাংশনটি কেবলমাত্র চেক করা উচিত companyn অন্যান্য স্কিমা নয়, স্কিমা পাস হয়েছে ।

প্রদত্ত টেবিল যদি উভয় publicএবং পাস হওয়া স্কিমাতে উপস্থিত থাকে তবে ফাংশনটি ফিরে আসা উচিত true
এটি পোস্টগ্রিস 8.4 বা তার পরে এর জন্য কাজ করা উচিত।

উত্তর:


283

এটি নির্ভর করে আপনি ঠিক কী পরীক্ষা করতে চান ।

তথ্য স্কিম?

"সারণীটি বিদ্যমান কিনা" ( যারা জিজ্ঞাসা করছে না ) সন্ধানের জন্য, তথ্য স্কিমার ( information_schema.tables) কে জিজ্ঞাসাবাদ করা ভুল , কঠোরভাবে বলা হচ্ছে, কারণ ( প্রতি ডকুমেন্টেশন ):

কেবলমাত্র সেই টেবিলগুলি এবং দর্শনগুলি দেখানো হয়েছে যে বর্তমান ব্যবহারকারীর অ্যাক্সেস রয়েছে (মালিক হওয়ার উপায় বা কোনও সুযোগ সুবিধা পাওয়ার কারণে)।

@ কোংয়ের সরবরাহ করা ক্যোয়ারী ফিরে আসতে পারে FALSEতবে সারণীটি এখনও বিদ্যমান থাকতে পারে। এটি প্রশ্নের উত্তর:

কোনও টেবিল (বা দেখুন) বিদ্যমান আছে এবং বর্তমান ব্যবহারকারীর এতে অ্যাক্সেস রয়েছে কিনা তা কীভাবে পরীক্ষা করবেন?

SELECT EXISTS (
   SELECT FROM information_schema.tables 
   WHERE  table_schema = 'schema_name'
   AND    table_name   = 'table_name'
   );

তথ্য স্কিমা মূল সংস্করণ এবং বিভিন্ন আরডিবিএমএস জুড়ে বহনযোগ্য থাকার জন্য দরকারী। তবে বাস্তবায়ন ধীর, কারণ পোস্টগ্র্রেসকে মান মেনে চলার জন্য পরিশীলিত দৃষ্টিভঙ্গি ব্যবহার করতে হবে ( information_schema.tablesএটি একটি সহজ উদাহরণ)। এবং কিছু তথ্য (যেমন ওআইডি) সিস্টেম ক্যাটালগগুলি থেকে অনুবাদে হারিয়ে যায় - যা আসলে সমস্ত তথ্য বহন করে।

সিস্টেম ক্যাটালগ

আপনার প্রশ্ন ছিল:

টেবিলের অস্তিত্ব আছে কিনা তা কীভাবে পরীক্ষা করবেন?

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), সিকোয়েন্স , ভিউ , উপাদানযুক্ত দর্শন , সমন্বিত প্রকার এবং টোস্ট সারণী অন্তর্ভুক্ত রয়েছে ;

এই নির্দিষ্ট প্রশ্নের জন্য আপনি সিস্টেমের ভিউটিওpg_tables ব্যবহার করতে পারেন । প্রধান পোস্টগ্রাস সংস্করণগুলিতে কিছুটা সহজ এবং আরও বহনযোগ্য (যা এই প্রাথমিক ক্যোয়ারির জন্য উদ্বেগের বিষয় নয়):

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ালাই regclass

SELECT 'schema_name.table_name'::regclass

(Allyচ্ছিকভাবে স্কিমা-যোগ্য) টেবিল (বা সেই নামটি দখল করা অন্য কোনও বস্তু) উপস্থিত না থাকলে এটি একটি ব্যতিক্রম উত্থাপন করে।

তুমি কি সারণী নাম, এর একটি ঢালাই স্কিমা-যোগ্যতা অর্জন করেন তাহলে regclassডিফল্ট search_pathএবং আয় প্রথম টেবিলের জন্য OID পাওয়া যায় নি - বা একটি ব্যতিক্রম যদি টেবিল তালিকাভুক্ত স্কিমের কেউই হয়। নোট করুন যে সিস্টেম স্কিমা pg_catalogএবং pg_temp(বর্তমান সেশনের অস্থায়ী বস্তুর জন্য স্কিমা) স্বয়ংক্রিয়ভাবে এর অংশ search_path

আপনি এটি ব্যবহার করতে পারেন এবং একটি ফাংশনে একটি সম্ভাব্য ব্যতিক্রম ধরতে পারেন। উদাহরণ:

উপরের মতো একটি কোয়েরি সম্ভাব্য ব্যতিক্রমগুলি এড়িয়ে চলে এবং তাই কিছুটা দ্রুত।

to_regclass(rel_name) পোস্টগ্রিস 9.4+ এ

এখন অনেক সহজ:

SELECT to_regclass('schema_name.table_name');

Castালাই হিসাবে একই, কিন্তু এটি ফিরে ...

... নাম না পাওয়া গেলে ত্রুটি ছুঁড়ে ফেলার চেয়ে নাল


4
শেল থেকে:[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]
ব্রুলিওলো

1
আপনি pg_tables ব্যবহার করছেন না এমন কোনও কারণ আছে ?
m0meni

1
pg_tablesআসলে "একটি টেবিলের অস্তিত্ব আছে কিনা তা কীভাবে পরীক্ষা করবেন?" এর জন্য আসলে একটি ভাল ধারণা ? (জন্য চেক করা হচ্ছে টেবিল শুধুমাত্র ।, না অন্যান্য কাজের জন্য, মত উপরে বর্ণিত এছাড়াও, pg_tablesবিভিন্ন টেবিল জড়িত একটি দৃশ্য আছে ( pg_class, pg_namespace, pg_tablespace), একটি বিট আরো ব্যয়বহুল যা সবচেয়ে গুরুত্বপূর্ণ কারণ:। আমি ক্যোয়ারী ব্যবহার করছি pg_classসরাসরি এবং করেনি মনে pg_tablesযখন এই উত্তরটি লেখার আমি এখন এটা উপরে যোগ,
এরউইন Brandstetter

1
@ সেজ ৮৮: ঠিক আছে, আমি আমার ভুল মন্তব্যটি সরিয়েছি। আপনি pg_my_temp_schema()যদি প্রকৃত টেম্প স্কিমার বিদ্যমান থাকে তবে এর ওআইডি পেতে ব্যবহার করতে পারেন । (তবে information_schemaওআইডি অন্তর্ভুক্ত নয় এমন মতামত You আপনি পারতেন SELECT nspname FROM pg_namespace WHERE OID = pg_my_temp_schema()) আপনার পরীক্ষার কয়েকটি দুর্বলতা রয়েছে। একটি সঠিক পরীক্ষা হবে table_schema LIKE 'pg\_temp\_%'বা কঠোর: table_schema ~ '^pg_temp_\d+$'
এরউইন ব্র্যান্ডসেটেটার

1
@ পিটারক্রাউস আপনি 9.4 এর চেয়ে পুরনো পোস্টগ্রিজের সংস্করণে to_regclass ফাংশনটি ব্যবহার করার চেষ্টা করলে আপনি এই ত্রুটিটি পাবেন। 9.4+
spetz83

44

সম্ভবত তথ্য_সেমিমা ব্যবহার করুন :

SELECT EXISTS(
    SELECT * 
    FROM information_schema.tables 
    WHERE 
      table_schema = 'company3' AND 
      table_name = 'tableincompany3schema'
);

0

পোস্টগ্রাএসকিউএল 9.3 বা তার চেয়ে কমের জন্য ... বা যাকে পাঠ্যটিতে সমস্ত সাধারণীকরণ পছন্দ হয়

আমার পুরোনো SwissKnife গ্রন্থাগার তিন স্বাদে: relname_exists(anyThing), relname_normalized(anyThing)এবং relnamechecked_to_array(anyThing)Pg_catolog.pg_class টেবিল থেকে সমস্ত চেক এবং মানক ইউনিভার্সাল ডেটাটাইপগুলি ( বুলিয়ান , পাঠ্য বা পাঠ্য []) প্রদান করে।

/**
 * From my old SwissKnife Lib to your SwissKnife. License CC0.
 * Check and normalize to array the free-parameter relation-name.
 * Options: (name); (name,schema), ("schema.name"). Ignores schema2 in ("schema.name",schema2).
 */
CREATE FUNCTION relname_to_array(text,text default NULL) RETURNS text[] AS $f$
     SELECT array[n.nspname::text, c.relname::text]
     FROM   pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace,
            regexp_split_to_array($1,'\.') t(x) -- not work with quoted names
     WHERE  CASE
              WHEN COALESCE(x[2],'')>'' THEN n.nspname = x[1]      AND c.relname = x[2]
              WHEN $2 IS NULL THEN           n.nspname = 'public'  AND c.relname = $1
              ELSE                           n.nspname = $2        AND c.relname = $1
            END
$f$ language SQL IMMUTABLE;

CREATE FUNCTION relname_exists(text,text default NULL) RETURNS boolean AS $wrap$
  SELECT EXISTS (SELECT relname_to_array($1,$2))
$wrap$ language SQL IMMUTABLE;

CREATE FUNCTION relname_normalized(text,text default NULL,boolean DEFAULT true) RETURNS text AS $wrap$
  SELECT COALESCE(array_to_string(relname_to_array($1,$2), '.'), CASE WHEN $3 THEN '' ELSE NULL END)
$wrap$ language SQL IMMUTABLE;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.