Postgresql:如何仅在表不存在时创建表?

55
在Postgresql中,如何通过条件语句仅在表不存在时创建表?
代码示例将被赞赏。

1
如果您的表定义与现有表不匹配,您希望发生什么?出错、修改表或什么都不做?一些上下文会有所帮助。 - Kev
10个回答

99

我不确定这是何时添加的,但为了完整起见,我想指出在9.1版本(也许之前)可以使用IF NOT EXISTSIF NOT EXISTS仅在表不存在时创建该表。

示例:

CREATE TABLE IF NOT EXISTS users.vip
(
  id integer
)

如果表不存在,则会在架构users中创建一个名为vip的表。

来源


18
已在 9.1 版本中实施。 - Erwin Brandstetter

24
create or replace function update_the_db() returns void as
$$
begin

    if not exists(select * from information_schema.tables 
        where 
            table_catalog = CURRENT_CATALOG and table_schema = CURRENT_SCHEMA
            and table_name = 'your_table_name_here') then

        create table your_table_name_here
        (
            the_id int not null,
            name text
        );

    end if;

end;
$$
language 'plpgsql';

select update_the_db();
drop function update_the_db();

1
这个不考虑当前模式,也就是说,它会检查表是否存在于_任何_模式中,如果存在,则不会在当前模式中创建它。 - BuschnicK
1
我之前在相关问题中发布了一个非常相似但略微简化的版本。刚刚发现了这个。 - Erwin Brandstetter

16

只需创建表,无需担心它是否存在。如果不存在,则将被创建;如果存在,则该表不会被修改。您始终可以检查 SQL 查询的返回值,以查看在执行 create 语句时表是否存在。


6
大多数情况下,你确实不必担心。当创建发生在事务内时,它会导致事务被中止。 - diciu
25
就我个人而言,我认为这种答案或思维方式会鼓励糟糕的实践。如果我预期表可能已经存在,那么必须测试是否存在,而不是检查错误条件。也许在2011年,这种范式是有效的?但现在,如果试图创建已经存在的表,数据库管理系统将会产生一个错误。 - Jeff Maass

12

我认为检查pg_class表可能会帮助你,就像这样:

SELECT COUNT (relname) as a FROM pg_class WHERE relname = 'mytable'

if a = 0 then (CREATE IT)

敬礼。


7

这是一个老问题。我只是想再提供另一种解决方案。注意:其他更好的答案已经存在,这只是为了教育目的。

最简单的方法是像其他人所说的那样:如果你想保留现有数据,执行CREATE TABLE语句;如果你想创建一个全新的表,先执行DROP IF EXISTS,然后再执行CREATE TABLE语句。

另一种选择是查询系统表是否存在,然后根据情况进行处理。

SELECT true FROM pg_tables WHERE tablename = <table> [AND schemaname = <schema>];

使用中:

-- schema independent:
SELECT true FROM pg_tables WHERE tablename = 'foo';

-- schema dependent:
SELECT true FROM pg_tables WHERE tablename = 'foo' AND schemaname = 'bar';

如果匹配成功,将返回 true 值,否则应该返回一个空数据集。您可以使用该值来确定是否需要执行 CREATE TABLE 操作。


1
值得注意的是,如果您使用 AND schemaname = <schema>,那么像临时表这样的东西将存在,但会被放置在不同的模式中... - Mark Fowler

3

如果您正在运行Postgresql 9.1+,Skalli提供了最佳答案。

如果像我一样需要在Postgresql 8.4中执行此操作,则可以使用带有“duplicate_table”异常捕获的函数。

这将忽略当表已经存在时生成的错误,并继续生成其他错误。

下面是一个在Postgresql 8.4.10上运行的示例:

CREATE FUNCTION create_table() RETURNS VOID AS
$$
BEGIN
    CREATE TABLE my_table_name(my_column INT);
EXCEPTION WHEN duplicate_table THEN
    -- Do nothing
END;
$$
LANGUAGE plpgsql;

2
最简单的答案是:
catch{

#create table here

}

如果不存在表,则创建一个表,如果存在则产生错误并捕获该错误。

2

在创建表之前,我用Java和PostgreSQL检查表是否存在。希望这能帮助到某些人。 这里没有实现创建表的部分,只是检查表是否已经存在。 将数据库连接和表名传递进去,它应该返回表是否存在。

public boolean SQLTableExists(Connection connection, String tableName) {
    boolean exists = false;

    try {
        Statement stmt = connection.createStatement();
        String sqlText = "SELECT tables.table_name FROM information_schema.tables WHERE table_name = '" + tableName + "'";    
        ResultSet rs = stmt.executeQuery(sqlText);

        if (rs != null) {
            while (rs.next()) {
                if (rs.getString(1).equalsIgnoreCase(tableName)) {
                    System.out.println("Table: " + tableName + " already exists!");
                    exists = true;
                } else { 
                    System.out.println("Table: " + tableName + " does not appear to exist.");
                    exists = false;
                }

            }
        }

    } catch (SQLException sqlex) {
        sqlex.printStackTrace();
    }
    return exists;
}

2
你可能想在查询中包含 schema_name,以便针对不同模式中的相同表进行筛选。 - user330315

1

5
如果存在这张表,他不想删除它。如果不存在,他想要创建它。 - Peter Anselmo

0

尝试在表上运行查询。如果它抛出异常,则捕获该异常并创建一个新表。

try {
    int a =  db.queryForInt("SELECT COUNT(*) FROM USERS;");
}
catch (Exception e) {
    System.out.print(e.toString());
    db.update("CREATE TABLE USERS (" +
                "id SERIAL," +
                "PRIMARY KEY(id)," +
                "name varchar(30) NOT NULL," +
                "email varchar(30) NOT NULL," +
                "username varchar(30) NOT NULL," +
                "password varchar(30) NOT NULL" +
                ");");
}
return db;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接