sqlite 和“约束失败”同时选择和插入时出错
我正在研究迁移功能。它从旧表中读取数据并将其插入到新表中。所有这些东西都在低优先级的后台线程中工作。
我的伪代码步骤。
sqlite3_prepare_stmt (select statement)
sqlite3_prepare_stmt (insert statement)
while (sqlite3_step (select statement) == SQLITE_ROW)
{
get data from select row results
sqlite3_bind select results to insert statement
sqlite3_step (insert statement)
sqlite3_reset (insert statement)
}
sqlite3_reset (select statement)
我总是在 sqlite3_step(插入语句)
上收到“约束失败”错误。为什么会发生这种情况以及我该如何解决这个问题?
UPD:据我了解,发生这种情况是因为后台线程使用主线程中打开的数据库句柄。现在检查这个猜测。
UPD2:
sqlite> select sql from sqlite_master where tbl_name = 'tiles';
CREATE TABLE tiles('pk' INTEGER PRIMARY KEY, 'data' BLOB, 'x' INTEGER, 'y' INTEGER, 'z' INTEGER, 'importKey' INTEGER)
sqlite> select sql from sqlite_master where tbl_name = 'tiles_v2';
CREATE TABLE tiles_v2 (pk int primary key, x int, y int, z int, layer int, data blob, timestamp real)
I'm working on migration function. It reads data from old table and inserts it into the new one. All that stuff working in background thread with low priority.
My steps in pseudo code.
sqlite3_prepare_stmt (select statement)
sqlite3_prepare_stmt (insert statement)
while (sqlite3_step (select statement) == SQLITE_ROW)
{
get data from select row results
sqlite3_bind select results to insert statement
sqlite3_step (insert statement)
sqlite3_reset (insert statement)
}
sqlite3_reset (select statement)
I'm always getting 'constraint failed' error on sqlite3_step (insert statement)
. Why it's happend and how i could fix that?
UPD: As i'm understand that's happend because background thread use db handle opened in main thread. Checking that guess now.
UPD2:
sqlite> select sql from sqlite_master where tbl_name = 'tiles';
CREATE TABLE tiles('pk' INTEGER PRIMARY KEY, 'data' BLOB, 'x' INTEGER, 'y' INTEGER, 'z' INTEGER, 'importKey' INTEGER)
sqlite> select sql from sqlite_master where tbl_name = 'tiles_v2';
CREATE TABLE tiles_v2 (pk int primary key, x int, y int, z int, layer int, data blob, timestamp real)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这可能意味着您的插入语句违反了新表中的约束。可能是主键约束、唯一约束、外键约束(如果您使用的是
PRAGMAforeign_keys = ON;
)等等。您可以通过删除约束、更正数据或删除数据来解决此问题。放弃约束通常是一件坏事,但这取决于应用程序。
是否有令人信服的理由一次复制一行数据而不是一组数据?
如果您需要帮助识别约束,请编辑您的原始问题,并发布这两个 SQLite 查询的输出。
更新:根据这两个查询的输出,我只看到一个约束——每个表中的主键约束。如果您尚未在这些表上构建任何触发器,则唯一可能失败的约束是主键约束。该约束失败的唯一方法是尝试插入具有相同“pk”值的两行。
我想这可能会以几种不同的方式发生。
“pk”列。
更改或注入重复值
在将数据插入新的之前
桌子。
另一台计算机,正在插入或
在您不知情的情况下更新数据。
您可以通过运行此查询来确定旧表中是否存在重复的“pk”值。
您可能会考虑尝试使用 INSERT INTO 手动迁移数据。 。 。选择 。 。 . 如果失败,请添加 WHERE 子句来减小集合的大小,直到隔离出错误数据。
It probably means your insert statement is violating a constraint in the new table. Could be a primary key constraint, a unique constraint, a foreign key constraint (if you're using
PRAGMA foreign_keys = ON;
), and so on.You fix that either by dropping the constraint, correcting the data, or dropping the data. Dropping the constraint is usually a Bad Thing, but that depends on the application.
Is there a compelling reason to copy data one row at a time instead of as a set?
If you need help identifying the constraint, edit your original question, and post the output of these two SQLite queries.
Update: Based on the output of those two queries, I see only one constraint--the primary key constraint in each table. If you haven't built any triggers on these tables, the only constraint that can fail is the primary key constraint. And the only way that constraint can fail is if you try to insert two rows that have the same value for 'pk'.
I suppose that could happen in a few different ways.
the 'pk' column.
alters or injects a duplicate value
before inserting data into your new
table.
a different computer, is inserting or
updating data without your knowledge.
You can determine whether there are duplicate values of 'pk' in the old table by running this query.
You might consider trying to manually migrate the data using
INSERT INTO . . . SELECT . . .
If that fails, add a WHERE clause to reduce the size of the set until you isolate the bad data.我发现使用 sqlite 排除外键约束错误很麻烦,特别是在大型数据集上。然而,以下方法有助于识别违规关系。
PRAGMAforeign_keys = 0;
PRAGMAforeign_keys = 1;
PRAGMAforeign_key_check(table-name);
在我的例子中,它显示了13行无效的参考文献。
I have found that troubleshooting foreign key constraint errors with sqlite to be troublesome, particularly on large data sets. However the following approach helps identify the offending relation.
PRAGMA foreign_keys = 0;
PRAGMA foreign_keys = 1;
PRAGMA foreign_key_check(table-name);
In my case, it showed the 13 rows with invalid references.
以防万一有人登陆此处寻找“约束失败”错误消息,请确保您的
Id
列的类型为INTEGER
,而不是INTEGER (0, 15)
代码>或其他东西。背景
如果您的表有一个名为
Id
的列,类型为INTEGER
并设置为主键,SQLite 会将其视为内置的别名。在RowId
列中。该列的工作原理类似于自动增量列。就我而言,该列工作正常,直到某个表设计者(可能是 SQLite 人员为 Visual Studio 创建的表设计者)将列类型从 INTEGER 更改为 INTEGER (0, 15) 突然我的应用程序开始抛出约束失败
异常。Just in case anyone lands here looking for "Constraint failed" error message, make sure your
Id
column's type isINTEGER
, notINTEGER (0, 15)
or something.Background
If your table has a column named
Id
, with typeINTEGER
and set as Primary Key, SQLite treats it as an alias for the built-in columnRowId
. This column works like an auto-increment column. In my case, this column was working fine till some table designer (probably the one created by SQLite guys for Visual Studio) changed column type fromINTEGER
toINTEGER (0, 15)
and all of a sudden my application started throwingConstraint failed
exception.只是为了让它更清楚:
确保您使用的数据类型正确,我在创建 tmy 表时使用的是
int
而不是integer
,如下所示:id int 主键不为 null< /code>
并且我在几个小时内陷入了约束问题......
只需确保在创建数据库时正确输入数据类型即可。
just for making it more clearer :
make sure that you use data type correct , i was using
int
instead ofinteger
on creating tmy tables like this :id int primary key not null
and i was stuck on the constrain problem over hours ...
just make sure that to enter data type correctly in creating database.
发生此错误的原因之一是也为唯一行插入了重复数据。检查所有唯一键和重复数据的键。
One of the reasons that this error occurs is inserting duplicated data for a unique row too. Check your all unique and keys for duplicated data.
今天我遇到了类似的错误:
检查约束失败:配置文件
首先我读了这里什么是约束。
然后发现我需要检查数据库是如何创建的,因为我使用了 sqlalchemy 和 sqlite3 方言,所以我必须检查表
schema
。模式将显示实际的数据库结构。所以在这里我发现布尔值CHECK总是0或1,并且我使用列默认值作为“false”,所以每次我没有forum_copy_exist或forum_deleted值时,都会插入false,并且因为false是无效值,所以它会抛出错误,并且没有没有插入行。
因此更改数据库默认值是:
解决了问题。
在 postgresql 中,我认为 false 是有效值。所以这取决于数据库模式是如何创建的。
希望这将来能对其他人有所帮助。
Today i had similar error:
CHECK constraint failed: profile
First i read here what is constraint.
Then figured out that i need to check how database was created, because i used sqlalchemy and sqlite3 dialect, i had to check tables
schema
. Schema will show actual database structure.So here I found that boolean CHECK is always 0 or 1 and i used column default value as 'false', so each time i had no forum_copy_exist or forum_deleted value, false was inserted, and because false is invalid value it throws error, and didn't inserted row.
So changing database defaults to:
solved the issue.
In postgresql i think false is valid value. So it depends how database schema is created.
Hope this will help others in the future.
我在引用表上使用INTEGER作为INT,并在引用表中使用INTEGER作为外键。问题是你需要在这两个地方使用 INTEGER 。保持一致。因此在这两种情况下使用 INTEGER 解决了我的问题。 现在它运行起来就像魔法一样。
I was using INTEGER as INT on the referencing table, and INTEGER in the referenced table for the foreign key. The thing is that you need to use INTEGER in both places. Be consistent. So using INTEGER in both cases, solved my problem. Now it runs like magic.