当前位置: 首页 > 知识库问答 >
问题:

Liquibase SQL error--将非空的列添加到包含现有数据的表中

澹台欣怿
2023-03-14

我正在尝试使用Liquibase将一个数据库转换为另一个数据库。我有两个数据库,希望在其中一个数据库上运行SQL脚本,使其与另一个数据库相同。我正在使用Liquibase版本3.4.1和两个H2数据库。为了生成SQL脚本,我首先使用diffChangeLog命令生成diff xml,该命令运行良好。(实际上有一个问题:它生成的列类型为VARCHAR,autoIncrement设置为true,但可以手动删除)。然后,我使用命令updateSQL从diff-xml生成SQL文件。SQL文件包含以下行:

ALTER TABLE PUBLIC.USERS ADD ENABLED BOOLEAN(1) NOT NULL; 

最初,db包含一个名为USERS的表,该表有两列:USER和PASSWORD,其中有一行数据(user1,密码)。SQL脚本此时失败,因为它试图创建一个新列,该列的第一行条目将设置为NULL,但该列应该不是NULL。错误是:

错误:“ENABLED”列不允许为NULL;

SQL语句:ALTER TABLE PUBLIC. USERS ADD ENABLED BOOLEAN(1)Not NULL[23502-187]

SQLState:23502

错误代码:23502

错误发生在:ALTER TABLE PUBLIC。用户添加启用的布尔值(1)非空

我可以尝试手动删除NOT NULL条件,但这并不是在下面描述的所有情况下都有效。当我删除NOT NULL时,会发生以下情况:

执行以下行时(就在上面一行之后)会发生另一个相关错误:

ALTER TABLE PUBLIC.USERS ADD USERNAME VARCHAR(50) NOT NULL;  

注意,它试图添加“USERNAME”列,而不是原始数据库中已有的“USER”列。

它会产生相同的错误,当我删除NOT NULL时,会出现另一个错误:

错误:“用户名”列不能为空;

SQL语句:ALTER TABLE PUBLIC。用户添加CONSTRAINT CONSTRAINT_4主键(用户名)[90023-187]

SQLState:90023

错误代码:90023

错误发生在:ALTER TABLE PUBLIC。用户添加CONSTRAINT CONSTRAINT_4主键(用户名)

由于该列是主键,因此它不能为空。

有没有一种方法可以轻松解决这个问题?Liquibase中是否有一个选项可以消除这些错误?


共有3个答案

彭阳朔
2023-03-14

这取决于您的数据库。MySQL/Mariadb可以很简单:

<changeSet author="tibi" id="201803062100-1">
    <addColumn tableName="jhi_user">
        <column name="status" type="varchar(20)" value="ENABLED" />
        <constraints nullable="false" />
    </addColumn>
</changeSet>

H2不允许这样做,因此您需要:

<changeSet author="tibi" id="201803062100-1">
    <addColumn tableName="jhi_user">
        <column name="status" type="varchar(20)" value="ENABLED" />

    </addColumn>
    <addNotNullConstraint columnDataType="varchar(20)" columnName="status" tableName="jhi_user" />
</changeSet>

或者针对您的情况:

<changeSet author="tibi" id="201803062100-1">
    <addColumn tableName="jhi_user">
        <column name="status" type="boolean" value="0" />

    </addColumn>
    <addNotNullConstraint columnDataType="boolean" columnName="status" tableName="jhi_user" />
</changeSet>
东门焕
2023-03-14

当您添加一个非空列时,技巧是给它一个默认值。在Liquibase XML中,对于列定义,您需要这样的内容:

<column
    name="ENABLED"
    type="BOOLEAN(1)"
    defaultValue="0"
>

这应该生成一个默认为0的NOT NULL子句,适用于平台。

赵晨
2023-03-14

首先添加列,不带NOT NULL设置。然后更新现有行的列。最后,应用NOT NULL约束。

<addNotNullConstraint catalogName="cat"
            columnDataType="int"
            columnName="id"
            defaultNullValue="A String"
            schemaName="public"
            tableName="person"/>

我不建议使用defaultValue设置,因为如果您的行数较高,它可能会锁定表。对生产中的维护窗口非常不利。

 类似资料:
  • 目标: 需要向现有的Debezium MySQL连接器版本1.1.1添加一个新表。最终的连接器重新启动后,应使用更新的配置(table.whitelist中的新表)将表中的数据填充到主题中。 问题: 没有明确的策略来添加一个新表,该表将在初始快照完成后(连接器的前一个版本正在工作)与其数据一起添加到Kafka中。我们正在寻找类似于snapshot.select.statement.override

  • 问题内容: 我有一个表,其中的列包含一些空值。我想在该列上添加约束,而不将现有的null更新为非null值。我想保留现有的空值,并检查将来的行,它们是否包含此列的非空值。这可能吗?如何? 问题答案: 您可以添加未验证的约束-它不会查看现有行,但是会检查是否有任何新行或更新行。 请注意,除非满足约束,否则您将无法更新现有行。 另外,请注意,不利之处在于,优化器在制定计划时将无法利用此约束-它必须假设

  • 问题内容: 我正在显示此示例产品表。我需要在不使用结果集的情况下将所有表日期合并到一个jsp中。我尝试完成这一部分: 我需要将所有表数据添加到列表或?? 并使用方法将其退回我该怎么办? 问题答案: 使您的方法返回a 而不是单个。 然后,在您的JSP文件中,迭代返回的列表:

  • 很容易将列表列表转换为数据帧: 但是我如何将df转换回列表列表呢?

  • 问题内容: 与此问题类似,如何将空列添加到数据框?,我想知道向DataFrame添加一列空列表的最佳方法。 我想要做的基本上是初始化一列,然后遍历行以处理其中的一些行,然后在此新列中添加填充列表以替换初始化的值。 例如,如果下面是我的初始DataFrame: 然后,我最终希望得到这样的结果,其中每一行都经过单独处理(显示了示例结果): 当然,如果我尝试像使用其他任何常量一样进行初始化,它会认为我正

  • 问题内容: 我试图基于一个的数据创建“ n” 。我正在检查in的Integer值,并循环执行sql语句以创建与列中一样多的“ n” 。 这是我的代码: 我需要创建“ n”,但我不知道如何在循环之前声明类型并在for内填充。 现有数据类型: 新的数据类型: 问题答案: 您可以创建一个可变列表并填充它: 但是更好的方法(不使用可变数据结构)是将整数列表 映射 到DataFrames列表中: