簡體   English   中英

PostgreSQL 如果不存在則創建表

[英]PostgreSQL create table if not exists

在 MySQL 腳本中,您可以編寫:

CREATE TABLE IF NOT EXISTS foo ...;

……其他東西……

然后您可以多次運行腳本而無需重新創建表。

你如何在 PostgreSQL 中做到這一點?

此功能已Postgres 9.1 中實現

CREATE TABLE IF NOT EXISTS myschema.mytable (i integer);


對於舊版本,這里有一個功能可以解決它:

CREATE OR REPLACE FUNCTION create_mytable()
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   IF EXISTS (SELECT FROM pg_catalog.pg_tables 
              WHERE  schemaname = 'myschema'
              AND    tablename  = 'mytable') THEN
      RAISE NOTICE 'Table myschema.mytable already exists.';
   ELSE
      CREATE TABLE myschema.mytable (i integer);
   END IF;
END
$func$;

稱呼:

SELECT create_mytable();        -- call as many times as you want. 

筆記:

  • pg_tables中的列schemanametablename區分大小寫。 如果在CREATE TABLE語句CREATE TABLE雙引號引用標識符,則需要使用完全相同的拼寫。 如果不這樣做,則需要使用小寫字符串。 看:

  • PostgreSQL 列名是否區分大小寫?

  • pg_tables只包含實際的 該標識符可能仍被相關對象占用。 看:

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

  • 如果在執行此功能的作用,不具備必要的權限,以創建表,你可能想使用SECURITY DEFINER的功能,使其擁有與必要的權限另一個角色。 這個版本足夠安全。

試試這個:

CREATE TABLE IF NOT EXISTS app_user (
  username varchar(45) NOT NULL,
  password varchar(450) NOT NULL,
  enabled integer NOT NULL DEFAULT '1',
  PRIMARY KEY (username)
)

我從現有答案中創建了一個通用解決方案,可以對任何表重復使用:

CREATE OR REPLACE FUNCTION create_if_not_exists (table_name text, create_stmt text)
RETURNS text AS
$_$
BEGIN

IF EXISTS (
    SELECT *
    FROM   pg_catalog.pg_tables 
    WHERE    tablename  = table_name
    ) THEN
   RETURN 'TABLE ' || '''' || table_name || '''' || ' ALREADY EXISTS';
ELSE
   EXECUTE create_stmt;
   RETURN 'CREATED';
END IF;

END;
$_$ LANGUAGE plpgsql;

用法:

select create_if_not_exists('my_table', 'CREATE TABLE my_table (id integer NOT NULL);');

如果要從查詢參數中提取表名,則可以進一步簡化只采用一個參數。 我也遺漏了模式。

沒有 CREATE TABLE IF NOT EXISTS ......但你可以為此編寫一個簡單的過程,例如:

CREATE OR REPLACE FUNCTION execute(TEXT) RETURNS VOID AS $$
BEGIN
  EXECUTE $1;
END; $$ LANGUAGE plpgsql;


SELECT 
  execute($$
      CREATE TABLE sch.foo 
      (
        i integer
      )
  $$) 
WHERE 
  NOT exists 
  (
    SELECT * 
    FROM information_schema.tables 
    WHERE table_name = 'foo'
      AND table_schema = 'sch'
  );

此解決方案與 Erwin Brandstetter 的答案有些相似,但僅使用 sql 語言。

並非所有 PostgreSQL 安裝都默認使用 plpqsql 語言,這意味着您可能必須在創建函數之前調用CREATE LANGUAGE plpgsql ,然后必須再次刪除該語言,以使數據庫保持與之前相同的狀態(但僅如果數據庫開始時沒有 plpgsql 語言)。 看看復雜度是如何增長的?

如果您在本地運行腳本,添加 plpgsql 可能不是問題,但是,如果腳本用於在客戶處設置架構,則可能不希望在客戶數據庫中保留這樣的更改。

此解決方案的靈感來自Andreas Scherbaum 的帖子

-- Function which creates table
CREATE OR REPLACE FUNCTION create_table () RETURNS TEXT AS $$
    CREATE TABLE table_name (
       i int
    );
    SELECT 'extended_recycle_bin created'::TEXT;
    $$
LANGUAGE 'sql';

-- Test if table exists, and if not create it
SELECT CASE WHEN (SELECT true::BOOLEAN
    FROM   pg_catalog.pg_tables 
    WHERE  schemaname = 'public'
    AND    tablename  = 'table_name'
  ) THEN (SELECT 'success'::TEXT)
  ELSE (SELECT create_table())
END;

-- Drop function
DROP FUNCTION create_table();

沒有 CREATE TABLE IF NOT EXISTS ......但你可以為此編寫一個簡單的過程,例如:

CREATE OR REPLACE FUNCTION prc_create_sch_foo_table() RETURNS VOID AS $$
BEGIN

EXECUTE 'CREATE TABLE /* IF NOT EXISTS add for PostgreSQL 9.1+ */ sch.foo (
                    id serial NOT NULL, 
                    demo_column varchar NOT NULL, 
                    demo_column2 varchar NOT NULL,
                    CONSTRAINT pk_sch_foo PRIMARY KEY (id));
                   CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column ON sch.foo(demo_column);
                   CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column2 ON sch.foo(demo_column2);'
               WHERE NOT EXISTS(SELECT * FROM information_schema.tables 
                        WHERE table_schema = 'sch' 
                            AND table_name = 'foo');

         EXCEPTION WHEN null_value_not_allowed THEN
           WHEN duplicate_table THEN
           WHEN others THEN RAISE EXCEPTION '% %', SQLSTATE, SQLERRM;

END; $$ LANGUAGE plpgsql;

暫無
暫無

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

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