sqlite 删除时临时关闭级联

7cwmlq89  于 2023-06-23  发布在  SQLite
关注(0)|答案(1)|浏览(123)

我正在尝试使用数据库提供程序编写一个新的迁移来更新我们的sqlite数据库。在其文档ALTER TABLE中描述了更改色谱柱的过程。
我需要对一个父表进行更改,该表具有外键约束设置为删除时级联的子表。我已经实现了文档中的步骤,但是当我删除旧表时,它会删除子表中的所有记录。文档中的步骤:
1.创建新表
1.复制数据
1.删除旧表
1.将新的重命名为旧的

/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.Sql(
        "PRAGMA foreign_keys=off;\r\n" +
        "PRAGMA ignore_check_constraints = on;" +
        "PRAGMA legacy_alter_table=on;\r\n" +

        // Step 1.
        "CREATE TABLE \"PROCEDURES_TEMP\" (\r\n" +
        "    \"PROCEDURE_ID\" TEXT NOT NULL CONSTRAINT \"PK_PROCEDURES\" PRIMARY KEY,\r\n" +
        "    \"DESCRIPTION\" TEXT NOT NULL,\r\n" +
        "    \"IS_PRODUCTION\" INTEGER NOT NULL DEFAULT (0)\r\n" +
        ");\r\n" +

        // Step 2.
        "INSERT INTO \"PROCEDURES_TEMP\"(\"PROCEDURE_ID\", \"DESCRIPTION\", \"IS_PRODUCTION\")\r\n" +
                            "SELECT \"PROCEDURE_ID\", \"DESCRIPTION\", \"IS_PRODUCTION\" \r\n" +
                            "FROM \"PROCEDURES\";\r\n" +
            
        // Step 3.
        "DROP TABLE \"PROCEDURES\";\r\n" +
        // Step 4.
        "ALTER TABLE \"PROCEDURES_TEMP\" RENAME TO \"PROCEDURES\";\r\n" +

        "PRAGMA foreign_keys=on;\r\n" +
        "PRAGMA ignore_check_constraints = off;" +
        "PRAGMA legacy_alter_table=off;\r\n"
        );
}

子表看起来像

CREATE TABLE \"FLOWS\" (
    \"FLOW_ID\" INTEGER NOT NULL,
    \"PROCEDURE_ID\" TEXT NOT NULL,
    \"DESCRIPTION\" TEXT NULL,
    \"SEQUENCE_NUMBER\" INTEGER NOT NULL DEFAULT (1),
    CONSTRAINT \"PK_FLOWS\" PRIMARY KEY (\"FLOW_ID\", \"PROCEDURE_ID\"),
    CONSTRAINT \"FK_FLOWS_PROCEDURES\" FOREIGN KEY (\"PROCEDURE_ID\") REFERENCES \"PROCEDURES\"  (\"PROCEDURE_ID\") ON DELETE CASCADE\r\n);

我不是100%的级联删除是什么导致的问题。如果我不删除旧表,所有数据仍然存在。我已经尝试了许多不同的版本,比如将其改为两个操作而不是一个。是否需要临时存储所有子数据并重新插入?我是不是漏掉了什么?

0qx6xfy6

0qx6xfy61#

我在更改两个表的迁移中遇到了此问题。问题是一个表是另一个表的父表。
自动生成的迁移代码逐个独立地处理这两个表。在我的例子中,解决方案是重新排序代码,首先将 * 两个 * 表的行复制到临时表,然后 * 删除并重新创建两个表并复制回数据。
自动生成的代码看起来像这样(简化):

-- child_table
CREATE TEMPORARY TABLE child_table_tmp ...;
INSERT INTO child_table_tmp SELECT * FROM child_table;
DROP TABLE child_table;
CREATE TABLE child_table ...;
INSERT INTO child_table SELECT * FROM child_table_tmp;
DROP TABLE child_table_tmp;

-- parent_table
CREATE TEMPORARY TABLE parent_table_tmp ...;
INSERT INTO parent_table_tmp SELECT * FROM parent_table;
DROP TABLE parent_table;
CREATE TABLE parent_table ...;
INSERT INTO parent_table SELECT * FROM parent_table_tmp;
DROP TABLE parent_table_tmp;

我重新排序了语句,这样做:

-- save child_table
CREATE TEMPORARY TABLE child_table_tmp ...;
INSERT INTO child_table_tmp SELECT * FROM child_table;

-- save parent_table
CREATE TEMPORARY TABLE parent_table_tmp ...;
INSERT INTO parent_table_tmp SELECT * FROM parent_table;

-- create new tables and re-insert data
DROP TABLE child_table;
CREATE TABLE child_table ...;
INSERT INTO child_table SELECT * FROM child_table_tmp;
DROP TABLE child_table_tmp;

DROP TABLE parent_table;
CREATE TABLE parent_table ...;
INSERT INTO parent_table SELECT * FROM parent_table_tmp;
DROP TABLE parent_table_tmp;

如果您的子表没有被迁移更改,您仍然可以通过预先保存子表行并重新插入它们来解决这个问题。

相关问题