【问题标题】:Sqlite error: No such table main.table_name existsSqlite 错误:没有这样的表 main.table_name 存在
【发布时间】:2019-12-06 17:55:37
【问题描述】:

在我的 UWP 应用程序中,我在 sqlite db 的 App Start 上创建表。此外,我编写了各种 Alter 命令,其中我检查安装的应用程序是否包含 Customertbl 中的相应列,并将 Customertbl 表重命名为 Customertbl_old 并创建新表 Customertbl,最后我将 Customertbl_old 表中的所有行存储到 Customertbl 表中。然后我删除表 Customertbl_old。 现在,到这一部分为止一切正常,但是,当我尝试在 OwnerTbl 中删除/插入一行时,它会抛出一个异常,说

Sqlite 错误:没有这样的表 main.Customertbl_old 存在。

//**Code where a column name is updated by creating new table**
string tableCommand = "PRAGMA table_info(Recordings)"; 
SqliteCommand createTable = new SqliteCommand(tableCommand, db);
SqliteDataReader query = createTable.ExecuteReader(); 
tableCommand = "PRAGMA foreign_keys = off; " + " 
BEGIN TRANSACTION; " +
" ALTER TABLE Customertbl RENAME TO _Customertbl_old; " +
" CREATE TABLE Customertbl ( " + " ID INTEGER PRIMARY KEY AUTOINCREMENT, " + " CustomerName NVARCHAR(100) NULL, " + " Password NVARCHAR(100) NULL, " + " 
pkID INTEGER NULL, " + " ActivityName NVARCHAR(255) NULL);" +
 " INSERT INTO Customertbl(Name,Password) " + " SELECT Name,Password " + " 
FROM _Customertbl_old ;" + " COMMIT; " + " PRAGMA foreign_keys=on; " + " 
DROP TABLE 
_Customertbl_old";

// **code where exception occur**
using (SqliteConnection db = new 
SqliteConnection("Filename=" + App.dbName)) 
{ 
db.Open(); 
SqliteCommand deleteCommand = new SqliteCommand(); 
try 
{ 
    deleteCommand.Connection = db; 
    deleteCommand.CommandText = "DELETE FROM Ownertbl where fkId = @id";  
    deleteCommand.Parameters.AddWithValue("@id", id);  
    deleteCommand.ExecuteReader()//here the exception occur ;  
    db.Close(); 
 } 
}

【问题讨论】:

  • 这是预期的,因为你放弃了它?如果不了解有关架构的更多信息,就很难判断出了什么问题。导致错误的确切陈述也会有所帮助。
  • 您使用的是哪个版本的 SQLite?最近的版本更新了 ALTER TABLE 命令以自动重命名某些内容(包括 PK 引用)。这意味着更改表(重命名、新建、移动数据)的旧方法可能不再有效,除非您使用pragma legacy_alter_table=ON。见ALTER TABLE。或者,您可以直接更改表格。
  • 谢谢大家,@CPerkins 感谢分享链接link,它解释了重命名 sqlite 表中的列的正确方法。这修复了异常。 :)
  • 感谢先分享的TripeHound。我只是努力做一些进一步的澄清。很高兴它有帮助。
  • 是的,但仅供参考,在我的工作中,我没有使用 @TripeHound 提到的 pragma legacy_alter_table=ON。我用过(创建新的、移动数据、删除旧的、用旧名称重命名)

标签: c# sqlite uwp


【解决方案1】:

TL;DR

如果由于将 SQLite 升级到 3.26 或更高版本而导致以前使用的 ALTER TABLE... 中断,则“快速修复”是在进行这些更改之前使用 PRAGMA legacy_alter_table=ON。但是,重新组织命令可能会更好(请参阅“安全方式)。如果您正在使用 3.26 后版本的 SQLite 开始一个新项目,我绝对建议您使用“安全方式”并避免使用 PRAGMA

发生了什么

您的问题是由于在版本 3.25.0 (2018-09-15) 和 3.26.0 (2018-12) 中对 SQLite 的 ALTER TABLE 命令所做的更改而出现的-01)。官方文档见SQLite官网ALTER TABLE

在此版本之前,重命名表(例如,从 MY_TABLEA_BETTER_NAMED_TABLE更改了表的名称。对该表的任何引用(即在外键 (FK) 约束或触发器中)都没有重命名。如果目标是重命名表,这可以合理地被视为一个错误,因为没有(简单的、官方的)更改这些引用的方法,并且您将得到一个不一致的数据库.

上述更改通过将对表名称的更改传播到任何此类引用中来“修复”此问题。因此,您可以重命名 FK 约束或触发器引用的表,并保留一致的数据库。

当它引起问题时

由于ALTER TABLE 命令的功能非常有限(与非 Lite 数据库引擎相比),OP 的问题间接地出现了。在 SQLite 中,它所能做的就是更改表名、列名或添加新列(到行的“末尾”)。如果您需要对表执行比这更复杂的操作,则必须“创造性地”(本质上是创建一个新的替换表并从旧表中填充它)。但是,有两种方法可以做到这一点,其中一种方法被上述更改“破坏”了“尝试提供更多帮助”。

安全的方式

  • 使用您需要的所有新属性创建一个新的(例如MY_TABLE_NEW)。

  • 将现有数据从MY_TABLE 迁移到MY_TABLE_NEW(酌情添加默认值/缺失值)。

  • 删除原表MY_TABLE。此时,任何引用 MY_TABLE 的 FK 约束和触发器都会失败,但这并不重要。

  • 使用ALTER TABLE MY_TABLE_NEW RENAME TO MY_TABLE 将格式正确的新表格的名称改回原始表格的名称。现在将再次满足任何 FK 约束/触发器引用(假设它们不是针对已删除的列!)

以上内容在更改前后均有效。在更改之前,不注意 FK 约束/触发器;更改后,将不再有对 MY_TABLE_NEW 的引用,因此不会传播任何内容。

破碎之路

在更改之前,以下过程同样适用:

  • 使用ALTER TABLE MY_TABLE RENAME TO MY_TABLE_OLD。此时,在旧版本中任何 FK 约束/触发器都会不一致,但这没关系。

  • 创建一个 replacementMY_TABLE,其中包含您需要的所有新属性。现在将满足所有引用。

  • 将现有数据从MY_TABLE_OLD 迁移到MY_TABLE(酌情添加默认值/缺失值)。

  • 删除原来的(但重命名的)表MY_TABLE_OLD

问题出现在新版本中,因为它将重命名对原始表 (MY_TABLE) 的所有引用,以便它们现在引用即将被删除的表 (MY_TABLE_OLD)。其他步骤都不会影响这些引用,因此您会得到一个不一致的数据库(对不存在的 MY_TABLE_OLD 的引用)。

修复

要么将表格操作步骤的顺序更改为 安全方式 中的步骤,要么 - 如 ALTER TABLE 页面上所述 - 在 ALTER TABLE 命令之前发出命令 PRAGMA legacy_alter_table=ON。这将防止“改进”行为将对 MY_TABLE 的引用重命名为 MY_TABLE_OLD

【讨论】:

  • 如果你可以在你的帖子前加上 TL;DR: 使用 PRAGMA legacy_alter_table=ON
  • @Max 经过一番深思熟虑,我已经这样做了……但是,在大多数情况下,我建议重新排序命令,这样就不需要 pragma
  • 我已经用旧的方式重命名了一个表,并且花了几个小时来修复,因为我没有足够的经验一开始意识到引用表也必须被替换,而不仅仅是复制错误的表。
  • 安全方式就像一个魅力!谢谢!!
猜你喜欢
  • 2010-12-29
  • 2016-11-18
  • 2015-05-11
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
  • 2017-02-09
  • 2015-09-07
相关资源
最近更新 更多