PostgreSQL:创建表,如果不存在AS

use*_*836 20 sql postgresql create-table

我正在使用PostgreSQL并且是一个SQL初学者.我正在尝试从查询中创建一个表,如果我运行:

CREATE TABLE table_name AS
   (....query...)
Run Code Online (Sandbox Code Playgroud)

它工作得很好.但是如果我添加'if not exists'并运行:

CREATE TABLE IF NOT EXISTS table_name AS
   (....query...)
Run Code Online (Sandbox Code Playgroud)

使用完全相同的查询,我得到:

ERROR: syntax error at or near "as"
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点?

IMS*_*SoP 16

CREATE TABLE AS被认为是来自普通CREATE TABLE的单独语句,直到Postgres版本9.5(请参阅changelog条目)不支持IF NOT EXISTS子句.(请务必查看您所使用版本的正确手册版本.)

虽然不太灵活,但CREATE TABLE ... LIKE在某些情况下语法可能是另一种选择; 它不是从SELECT语句中获取其结构(和内容),而是复制另一个表或视图的结构.

因此,你可以写这样的东西(未经测试); 如果表已经填充,最后的插入是一种相当混乱的方式:

CREATE OR REPLACE VIEW source_data AS SELECT * FROM foo NATURAL JOIN bar;

CREATE TABLE IF NOT EXISTS snapshot LIKE source_data;

INSERT INTO snapshot
SELECT * FROM source_data
WHERE NOT EXISTS ( SELECT * FROM snapshot );
Run Code Online (Sandbox Code Playgroud)

或者,如果要丢弃以前的数据(例如,放弃的临时表),可以有条件地删除旧表,并无条件地创建新表:

DROP TABLE IF EXISTS temp_stuff;

CREATE TEMPORARY TABLE temp_stuff AS SELECT * FROM foo NATURAL JOIN bar;
Run Code Online (Sandbox Code Playgroud)


Erw*_*ter 6

CREATE TABLE IF NOT EXISTS ...在 Postgres 9.1 中添加。看:

Postgres 9.0 或更高版本

如果您打算为此编写一个函数,请基于系统目录表pg_class,而不是基于信息模式统计信息收集器(只有在激活时才存在)中的视图。

CREATE OR REPLACE FUNCTION create_table_qry(_tbl text
                                          , _qry text
                                          , _schema text = NULL)
  RETURNS bool
  LANGUAGE plpgsql AS
$func$
DECLARE
   _sch text := COALESCE(_schema, current_schema());
BEGIN
   IF EXISTS (
      SELECT FROM pg_catalog.pg_class c
      JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
      WHERE  n.nspname = _sch
      AND    c.relname = _tbl
      ) THEN
   
      RAISE NOTICE 'Name is not free: %.%',_sch, _tbl;
      RETURN  FALSE;
   ELSE
      EXECUTE format('CREATE TABLE %I.%I AS %s', _sch, _tbl, _qry);

      RAISE NOTICE 'Table created successfully: %.%',_sch, _tbl;
      RETURN  TRUE;
   END IF;
END
$func$;
Run Code Online (Sandbox Code Playgroud)

该函数采用表名和查询字符串,以及可选的模式来创建表(默认为当前模式)。

注意=在函数头和:=函数体中的正确使用:

还要注意标识符如何转义为标识符。您不能使用regclass,因为该表尚不存在: