我正在使用SQLite,它不支持向現有表添加約束

所以我不能做這樣的事情(僅作為一個例子):

ALTER TABLE [Customer]
ADD CONSTRAINT specify_either_phone_or_email
CHECK (([Phone] IS NOT NULL) OR ([Email] IS NOT NULL));

這種情況有沒有解決方法?

我知道:

  • 我可以為新表添加約束,但它不是新的(它由我的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;

要讀取模式,請在sqlite3命令行shell中執行.schema Customer 。這為您提供了CREATE TABLE語句,您可以編輯和執行該語句。


要更改表格,您可以使用後門。

首先,閱讀實際的表定義(這與你從.schema得到的相同):

SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'Customer';

將CHECK約束添加到該字符串,然後使用PRAGMA writable_schema = 1啟用對sqlite_master寫訪問權限;並將新表定義寫入其中:

UPDATE sqlite_master SET sql='...' WHERE type='table' AND name='Customer';

然後重新打開數據庫。

警告 :這僅適用於不更改表的磁盤格式的更改。如果您確實進行了任何更改記錄格式的更改(例如添加/刪除字段,或修改rowid,或添加需要內部索引的約束),那麼您的數據庫將會爆炸。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow