chi*_*7CC 3 sqlite foreign-keys typeorm
我使用 TypeORM (v0.2.18) 和 Node.js (v12.7.0) 在 SQLite 数据库中执行迁移。
这是我的情况:我有一个名为 的表country和一个名为 的表workflow。我想删除其中一列名为 的列name,country但通过该列进行workflow引用country。
使用 SQLite 的 DB Browser,我可以使用以下语句成功删除该列:
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;
Run Code Online (Sandbox Code Playgroud)
我在 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");
}
...
Run Code Online (Sandbox Code Playgroud)
但我收到这个错误:
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: []
}
Run Code Online (Sandbox Code Playgroud)
为什么它可以在 SQLite 的 DB Browser 中工作,但不能在 TypeORM 中工作?就像它忽略了 PRAGMA 语句一样。
基于此,我尝试同时使用PRAGMA foreign_keysand PRAGMA legacy_alter_table(分别将它们设置为 OFF 和 ON(在任何操作之前)以及 ON 和 OFF(在任何操作之后))。
up()我尝试在函数内部和外部使用 PRAGMA 。外部意味着我将之前和之后的语句放入await typeOrmConnection.runMigrations()我的文件中main.ts,例如await typeOrmConnection.query("PRAGMA foreign_keys=OFF").
小智 5
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();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3457 次 |
| 最近记录: |