SQLite-以外键关系更改父表

时间:2018-11-08 17:47:09

标签: sqlite foreign-keys

当前,在3.25.2版中,SQLite仅对alter table支持有限。例如。您不能更改列的数据类型(类型相似性)或删除列。

通常的解决方法是使用所需的架构创建一个新表,将原始表中的数据填充其中,删除原始表,然后重命名新表。但是,如果原始表是具有外键关系的父表怎么办?

official solution正在关闭外键,进行所需的更改,然后再打开外键。但是我对此有点恼火,因为这PRAGMA foreign_keys =在交易内部不会生效,因此需要在发行之前和之后进行发行。

我想改用延迟外键。 我有3个查询,其中一个似乎有效,另外两个则无效。我的问题如下:

  • 看似有效的查询是否按设计工作?还是只是一个由多个因素组成的幸运星座,并且根据数据库中的其他表或新数据,将来可能会破坏它?有点像C ++中的未定义行为?
  • 为什么其他的都不起作用?它们与第一个有何不同?

设置

PRAGMA foreign_keys = OFF;

DROP TABLE IF EXISTS Parent;
CREATE TABLE Parent(A TEXT UNIQUE, COLUMN_TO_DROP FLOAT);
INSERT INTO Parent VALUES('whatever', 0.0);

DROP TABLE IF EXISTS Child;
CREATE TABLE Child(C TEXT REFERENCES Parent(A) DEFERRABLE INITIALLY DEFERRED);
INSERT INTO Child VALUES('whatever');

PRAGMA foreign_keys = ON;

查询1-似乎按预期工作

BEGIN TRANSACTION;
CREATE TABLE Temp AS SELECT A FROM Parent;
DROP TABLE Parent;
CREATE TABLE Parent (A TEXT UNIQUE);
INSERT INTO Parent SELECT * FROM Temp;
DROP TABLE Temp;
COMMIT;

Query2-在选择[...]失败时创建[...]

BEGIN TRANSACTION;
CREATE TABLE Temp AS SELECT A FROM Parent;
DROP TABLE Parent;
CREATE TABLE Parent AS SELECT * FROM Temp;     -- different from Query1
CREATE UNIQUE INDEX ParentIndex on Parent(A);  -- different from Query1
DROP TABLE Temp;
COMMIT;

结果:

sqlite> PRAGMA foreign_key_check;
sqlite> .schema
CREATE TABLE Child(C TEXT REFERENCES Parent(A) DEFERRABLE INITIALLY DEFERRED);
CREATE TABLE Parent(A TEXT);
CREATE UNIQUE INDEX ParentIndex on Parent(A);
sqlite> SELECT * FROM Parent;
whatever

Query3-插入[...]失败

BEGIN TRANSACTION;
CREATE TABLE Temp (A TEXT UNIQUE);      -- different from Query1
INSERT INTO Temp SELECT A FROM Parent;  -- different from Query1
DROP TABLE Parent;
CREATE TABLE Parent (A TEXT UNIQUE);
INSERT INTO Parent SELECT * FROM Temp;
DROP TABLE Temp;
COMMIT;

结果:

sqlite> PRAGMA foreign_key_check;
sqlite> .schema
CREATE TABLE Child(C TEXT REFERENCES Parent(A) DEFERRABLE INITIALLY DEFERRED);
CREATE TABLE Parent (A TEXT UNIQUE);
sqlite> SELECT * FROM Parent;
whatever

请注意,PRAGMA foreign_key_check在任何情况下均未报告任何问题。

0 个答案:

没有答案