Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
向现有SQLite表添加约束_Sqlite_Database Schema_Entity Framework Core_Alter Table_Check Constraints - Fatal编程技术网

向现有SQLite表添加约束

向现有SQLite表添加约束,sqlite,database-schema,entity-framework-core,alter-table,check-constraints,Sqlite,Database Schema,Entity Framework Core,Alter Table,Check Constraints,我正在使用SQLite,它将添加到现有表中 所以我不能做这样的事情(举个例子): 此场景是否有解决方法? 我知道: 我可以为一个新表添加一个约束,但它不是新的(它是由我的ORM、EF-Core生成的) 我可以进行“表重建”(重命名表、创建新表、复制旧数据、删除临时表),但这似乎非常复杂 想法 我是否可以通过某种方式将该表复制到一个新表中,并对模式进行一些更改 或者以某种方式“获取”模式,并在SQL脚本中编辑它,然后使用该模式添加一个表 要复制带有某些架构更改的表,必须手动创建和复制: BE

我正在使用SQLite,它将添加到现有表中

所以我不能做这样的事情(举个例子):

此场景是否有解决方法?

我知道:

  • 我可以为一个新表添加一个约束,但它不是新的(它是由我的ORM、EF-Core生成的)
  • 我可以进行“表重建”(重命名表、创建新表、复制旧数据、删除临时表),但这似乎非常复杂
想法

  • 我是否可以通过某种方式将该表复制到一个新表中,并对模式进行一些更改
  • 或者以某种方式“获取”模式,并在SQL脚本中编辑它,然后使用该模式添加一个表

要复制带有某些架构更改的表,必须手动创建和复制:

BEGIN;
CREATE TABLE Customer_new (
    [...],
    CHECK ([...])
);
INSERT INTO Customer_new SELECT * FROM Customer;
DROP TABLE Customer;
ALTER TABLE Customer_new RENAME TO Customer;
COMMIT;

要读取架构,请在中执行
.schema Customer
。 这将为您提供CREATETABLE语句,您可以编辑和执行该语句


要在适当位置更改表,可以使用后门

首先,阅读实际的表定义(这与从
.schema
获得的定义相同):

将您的检查约束添加到该字符串,然后使用启用对
sqlite\u master
的写入访问,并将新表定义写入其中:

UPDATE sqlite_master SET sql='...' WHERE type='table' AND name='Customer';
然后重新打开数据库


警告:这仅适用于不改变表的磁盘格式的更改。如果您确实做了任何更改来更改记录格式(例如添加/删除字段,或修改rowid,或添加需要内部索引的约束),您的数据库将爆炸得可怕。

在我的情况下,使用CLI是不实际的,因为我正试图以编程方式执行,并且模式是由EF Core生成的。然而,“后门”选项很有趣。假设我在ORM创建表之后直接运行它,并且我所做的就是添加检查约束,就像您所解释的那样,它应该是安全的?您可以随时运行它。但是,如果表是空的,简单地删除并重新创建它(如第一个选项中所示)就不那么危险了。删除并重新创建它意味着我必须手工编写sql,而使用后门意味着我可以依靠ORM来正确处理它,并确保编译时的安全。在这种情况下,这是一个很有吸引力的选择。谢谢我应该做一个
PRAGMA writable_schema=0当我完成时?文档不清楚它是否在事务处理后粘住。您可以重新执行从
选择sqlite\u master中的sql
获得的内容。
SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'Customer';
UPDATE sqlite_master SET sql='...' WHERE type='table' AND name='Customer';