“如果不存在则创建表” - 如何也检查架构?
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。
【讨论】:
以上是关于“如果不存在则创建表” - 如何也检查架构?的主要内容,如果未能解决你的问题,请参考以下文章