“如果不存在则创建表” - 如何也检查架构?

Posted

技术标签:

【中文标题】“如果不存在则创建表” - 如何也检查架构?【英文标题】:"Create table if not exists" - how to check the schema, too? 【发布时间】:2011-01-29 10:40:13 【问题描述】:

是否有(或多或少)标准方法来检查名为mytable 的表是否存在,以及其架构是否与应有的相似?我正在尝试H2 database,并且

CREATE TABLE IF NOT EXISTS mytable (....)

语句显然只检查表的名称。如果有一个具有给定名称但架构不同的表,我希望得到一个异常。

【问题讨论】:

“同名的表”? “类似于它应该是的模式”?这对于通用查询工具来说太模糊了。 +1 因为我也想要这样的设施。不一定通过数据库,而是在工具/库中。 @Thilo:它应该是“具有给定名称的表”,现在已修复。 “类似于它应该的模式”我的意思是如果存在一个名为mytable 的表,它的模式必须等于我提供给查询的模式;否则我想得到某种错误。这是一个完美定义的查询,所以我想知道是否(如果没有,为什么不)有一种方法来表达它。实际上,我很惊讶“如果不存在”似乎只检查名称。 好主意,也想拥有这样的东西!不过,我从未听说过能够做到这一点的 SQL 构造。 【参考方案1】:
SELECT  *
FROM    INFORMATION_SCHEMA.TABLES
WHERE   TABLE_NAME      = 'TableName'
    AND TABLE_SCHEMA    = 'public'

【讨论】:

您能详细说明一下吗?这是做什么的? 我照他说的做...它检查数据库中是否存在这样的表。 INFORMATION_SCHEMA (在某种程度上)是标准化的,因此该语句适用于大多数数据库。 它也适用于 MSSQL,但“默认”架构是“dbo” 这个答案没有做的是演示如何比较架构。不过,它越来越近了。可以对INFORMATION_SCHEMA.COLUMNS 使用查询并检查现有列是否符合预期并对此做出反应。但是,我认为使用命名/编号迁移和迁移表(如 EntityFramework 支持方式)会更容易且不易出错 - 特别是当您需要保留现有数据但由于架构更改而更改其存储方式时。【参考方案2】:

CREATE TABLE IF NOT EXISTS ... 不是标准 SQL 代码。

要做的是检查表是否已经在目录中。 例如,在 Java 中,您可能会执行以下操作: connection.getMetaData().getTables(connection.getCatalog(), null, null, null)

欲了解更多信息,请参阅javadoc java.sql.Connection。

【讨论】:

虽然也不会检查架构(当然,使用 MetaData,您可以自己检查,但这很乏味。JDBC MetaData 有一个可怕的 API。)。【参考方案3】:

双重答案:

(a) 表的存在应该由应用程序的安装过程来确保,而不是由应用程序本身在运行时来确保。

(b) 如果您确实认为您有正当理由偏离 (a),您可以尝试查询目录,这是一个由表组成的数据库,其结构或多或少由 INFORMATION_SCHEMA 规定SQL 标准。存在哪些表,它们有哪些列,这些列是哪些数据类型,声明了哪些键等等,都在里面。

【讨论】:

许多应用程序不希望使用单独的安装程序/更新程序脚本给用户带来麻烦,也不想在内部管理他们的数据库方案。即使他们不创建表,在启动时检查表模式以断言应用程序的完整性也是有意义的(而不是稍后某个时候因随机数据库错误而失败)。我并不是说这种方法总是合适的,但在某些情况下它是有效的。 是的,我也认为虽然 a) 可能是通常的方式,但它类似于,说,“C: 驱动器的存在是应该通过安装程序来确保一个应用程序,而不是应用程序本身在运行时。”。但是一个严肃的应用程序不应该对环境做任何假设。相反,它应该检查它。环境会发生变化 - 迟早会发生变化。【参考方案4】:

我不知道有任何数据库本身具有此功能。

没有使用过(我自己编写了代码),但Apache DdlUtils 可能会有所帮助。

这是一件棘手的事情,特别是如果您希望它与不同的数据库供应商合作。 此外,对于模式需要有多相似才能通过,可能存在不同的意见。列名、列顺序、列类型、主键定义:当然。但是约束、约束的名称、表空间定义等等呢?

【讨论】:

我明白了,事情可能没有我想的那么简单。尽管如此,鉴于这是几乎所有使用任何数据库的软件都应该进行的检查,因此没有标准解决方案真是令人惊讶。【参考方案5】:

简单地说:

IF NOT EXISTS (SELECT 0 
           FROM INFORMATION_SCHEMA.TABLES 
           WHERE TABLE_SCHEMA = 'name_of_schema' 
           AND TABLE_NAME = 'name_of_table')
 BEGIN
     CREATE TABLE [name_of_schema].[name_of_table]
     (
       ...
     )
 END

更多示例,请查看here。

【讨论】:

以上是关于“如果不存在则创建表” - 如何也检查架构?的主要内容,如果未能解决你的问题,请参考以下文章

PDO MYSQL 如果不存在则创建表并找出它是不是已创建

MYSQL:如果不存在则创建表

Bigquery:如果不存在则创建表并使用 Python 和 Apache AirFlow 加载数据

访问:如果表不存在则创建表

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

插入表,如果表不存在,则创建表然后插入