簡體   English   中英

如何檢查給定模式中是否存在表

[英]How to check if a table exists in a given schema

Postgres 8.4 和更高版本的數據庫包含public表和company模式中的公司特定表。
company架構名稱始終以'company'開頭並以公司編號結尾。
所以可能有這樣的模式:

public
company1
company2
company3
...
companynn

應用程序始終適用於一家公司。
search_path在 odbc 或 npgsql 連接字符串中相應指定,例如:

search_path='company3,public'

您將如何檢查給定的表是否存在於指定的companyn模式中?

例如:

select isSpecific('company3','tablenotincompany3schema')

應該返回false ,並且

select isSpecific('company3','tableincompany3schema')

應該返回true

在任何情況下,function 應該只檢查companyn模式是否通過,而不是其他模式。

如果給定的表同時存在於public模式和傳遞的模式中,則 function 應該返回true
它應該適用於 Postgres 8.4 或更高版本。

這取決於您要准確測試什么

信息架構?

要查找“表是否存在”(無論是誰詢問),嚴格來說,查詢信息模式( 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是一個相當簡單的例子)。 並且一些信息(如 OID)在從系統目錄的翻譯中丟失了——它實際上攜帶了所有信息。

系統目錄

你的問題是:

如何檢查表是否存在?

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_classpg_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'
   );

替代方法: regclassregclass

SELECT 'schema_name.table_name'::regclass

如果(可選模式限定)表(或占用該名稱的其他對象)不存在,則會引發異常

如果您沒有對表名進行模式限定,則轉換為regclass默認為search_path並返回找到的第一個表的 OID - 如果該表不在列出的模式中,則返回異常。 請注意,系統模式pg_catalogpg_temp (當前會話的臨時對象的模式)自動成為search_path一部分。

您可以使用它並在函數中捕獲可能的異常。 例子:

像上面這樣的查詢避免了可能的異常,因此稍微快一點。

Postgres 9.4+ 中的to_regclass(rel_name)

現在簡單多了:

SELECT to_regclass('schema_name.table_name');

與演員表相同, 它返回......

... null 而不是在未找到名稱時拋出錯誤

也許使用information_schema

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

對於 PostgreSQL 9.3 或更低版本...或者誰喜歡全部標准化為文本

我的舊 SwissKnife 庫的三種風格: relname_exists(anyThing)relname_normalized(anyThing)relnamechecked_to_array(anyThing) 所有來自pg_catalog.pg_class表的檢查,並返回標准通用數據類型( booleantexttext [] )。

/**
 * 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;

來自https://www.postgresql.org/docs/current/app-psql.html#APP-PSQL-PATTERNS

例如,\dt foo*。 bar顯示所有表名包含 bar 的表,這些表位於模式名以 foo 開頭的模式中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM