可以";PRAGMA foreign_keys=OFF";SQLite语句是否在TypeORM迁移中



我使用TypeORM(v0.2.18(和Node.js(v12.7.0(在我的SQLite数据库中执行迁移。

这就是我的情况:我有一个名为country的表和一个名为workflow的表。我想删除country中名为name的列之一,但workflow通过该列引用country

使用SQLite的DB浏览器,我可以使用以下语句成功删除该列:

PRAGMA foreign_keys=OFF;
CREATE TEMPORARY TABLE country_backup(id, createdAt, updatedAt, enabled, codeIso2);
INSERT INTO country_backup SELECT id, createdAt, updatedAt, enabled, codeIso2 FROM country;
DROP TABLE country;
CREATE TABLE country(id, createdAt, updatedAt, enabled, codeIso2);
INSERT INTO country SELECT id, createdAt, updatedAt, enabled, codeIso2 FROM country_backup;
DROP TABLE country_backup;
PRAGMA foreign_keys=ON;

我在这样的TypeORM迁移中使用了它:

...
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query("PRAGMA foreign_keys=OFF");
await queryRunner.query("CREATE TEMPORARY TABLE country_backup(id, createdAt, updatedAt, enabled, codeIso2)");
await queryRunner.query("INSERT INTO country_backup SELECT id, createdAt, updatedAt, enabled, codeIso2 FROM country");
await queryRunner.query("DROP TABLE country");
await queryRunner.query("CREATE TABLE country(id, createdAt, updatedAt, enabled, codeIso2)");
await queryRunner.query("INSERT INTO country SELECT id, createdAt, updatedAt, enabled, codeIso2 FROM country_backup");
await queryRunner.query("DROP TABLE country_backup");
await queryRunner.query("PRAGMA foreign_keys=ON");
}
...

但我得到了这个错误:

Error during migration run:
QueryFailedError: SQLITE_CONSTRAINT: FOREIGN KEY constraint failed
at new QueryFailedError (/.../api/src/error/QueryFailedError.ts:9:9)
at Statement.handler (/.../src/driver/sqlite/SqliteQueryRunner.ts:53:26)
at Statement.replacement (/.../api/node_modules/sqlite3/lib/trace.js:19:31)
at Statement.replacement (/.../api/node_modules/sqlite3/lib/trace.js:19:31) {
message: 'SQLITE_CONSTRAINT: FOREIGN KEY constraint failed',
errno: 19,
code: 'SQLITE_CONSTRAINT',
name: 'QueryFailedError',
query: 'DROP TABLE country',
parameters: []
}

为什么它能在SQLite的DB浏览器中工作,而不能在TypeORM中工作?它好像忽略了PRAGMA的声明。

基于此,我尝试了PRAGMA foreign_keysPRAGMA legacy_alter_table(分别设置为OFF和on(在任何操作之前(以及on和OFF(在任何动作之后((。

我尝试在up()函数内部和外部使用PRAGMA。在外部,这意味着我将await typeOrmConnection.runMigrations()之前和之后的语句放在main.ts文件中,如await typeOrmConnection.query("PRAGMA foreign_keys=OFF")

sqlite文档说,在执行多个语句时不能设置PRAGMA foreign_keys=off,所以我尝试了这个方法,并通过将PRAGMA语句与其他语句分离来实现它。

已经为传递给up()函数的查询运行器实例启动了事务。因此,立即结束现有事务,然后使用事务外查询关闭检查,然后启动另一个事务。

在新交易中写下剩余的非PRAGMA代码。

就在函数结束之前,提交内部事务,然后使用常规的单语句查询重新打开密钥检查,然后启动另一个事务(这样up()运行后就会自动关闭一些事务,否则会出现错误(。

public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.commitTransaction();
await queryRunner.query('PRAGMA foreign_keys=off');
await queryRunner.startTransaction();
// the rest of your queries
await queryRunner.commitTransaction();
await queryRunner.query('PRAGMA foreign_keys=on');
await queryRunner.startTransaction();
}

相关内容

最新更新