简体   繁体   English

使用 INSERT INTO 和子查询 SELECT 插入字段的前一个值

[英]Insert previous value of field using INSERT INTO and subquery SELECT

I have the following schema:我有以下架构:

CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, val INTEGER, previousval INTEGER)

I want to store the value val and automatically copy the previous value into the column previousval :我想存储值val并自动将先前的值复制到列previousval中:

id  val previousval
1   100 NULL
2   200 100
3   300 200

I tried the following query and SQLite gives me an error message I don't understand.我尝试了以下查询,SQLite 给了我一条我不明白的错误消息。

INSERT INTO test as test1 (id, val, previousval) VALUES (NULL, 1, (SELECT test2.val FROM test AS test2 WHERE test2.id<test1.id ORDER BY test2.id DESC LIMIT 1))
> no such column: test1.id

I tried another query:我尝试了另一个查询:

INSERT INTO test (id, val, previousval) VALUES (NULL, 100, (SELECT test2.val FROM test AS test2 WHERE test2.id<id ORDER BY test2.id DESC LIMIT 1)) 
INSERT INTO test (id, val, previousval) VALUES (NULL, 200, (SELECT test2.val FROM test AS test2 WHERE test2.id<id ORDER BY test2.id DESC LIMIT 1)) 
INSERT INTO test (id, val, previousval) VALUES (NULL, 300, (SELECT test2.val FROM test AS test2 WHERE test2.id<id ORDER BY test2.id DESC LIMIT 1)) 

The result is not what I expect and I don't understand why.结果不是我所期望的,我不明白为什么。

id  val previousval
1   100 NULL
2   200 NULL
3   300 NULL

I use sqlite-amalgamation-3310100.我使用 sqlite-amalgamation-3310100。 I also use SQLiteStudio for testing.我也使用 SQLiteStudio 进行测试。

How to automatically copy the value of a field into a column using INSERT INTO ?如何使用INSERT INTO自动将字段的值复制到列中?

The problem with your attempt is that you are trying to correlated the subquery with a value that is not yet inserted.您尝试的问题是您试图将子查询与尚未插入的值相关联。 That can't work.那是行不通的。

You could just do:你可以这样做:

insert into test as test1 (id, val, previousval) 
values(
    null, 
    1, 
    (select val from test order by id desc limit 1)
)

Note: if id is an auto-incremented key (as it looks like), then just skip that column when inserting:注意:如果id是一个自动递增的键(看起来像),那么在插入时跳过该列:

insert into test as test1 (val, previousval) 
values(
    1, 
    (select val from test order by id desc limit 1)
)

Bottom line, I would not actually recommend storing that derived information in the table itself: for example, if val is updated, then you need some additional processing to reset the following record.最重要的是,我实际上不建议将派生信息存储在表本身中:例如,如果更新了val ,那么您需要一些额外的处理来重置以下记录。

You can easily compute that information on the fly when needed, or put in a view.您可以在需要时轻松地即时计算该信息,或放入视图中。 If your version of SQLite supports window functions:如果您的 SQLite 版本支持 window 功能:

select id, val, lag(val) over(order by id) previousval from mytable

In earlier versions:在早期版本中:

select
    t.id,
    t.val,
    (select val from mytable t1 where t1.id < t.id order by t1.id desc limit 1) previousval
from mytable t

In your CREATE statement of the table you define the column id as:在表的CREATE语句中,您将列id定义为:

id INTEGER PRIMARY KEY 

and this means that it will be unique and auto incremented.这意味着它将是唯一的并且会自动递增。
But this does not mean that it will always increase.但这并不意味着它会一直增加。
If you delete a row, the next time that you will insert a new row the missing id value may be reused, so the logic that you want to apply will not work.如果删除一行,下次插入新行时可能会重复使用丢失的 id 值,因此您要应用的逻辑将不起作用。
So as it is explained here , you must disable the reuse of ids and this can be done by using the keyword AUTOINCREMENT in the definition of the column:因此,正如这里所解释的,您必须禁用 id 的重用,这可以通过在列的定义中使用关键字AUTOINCREMENT来完成:

CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, ...) 

Then you can insert new rows like this:然后你可以像这样插入新行:

INSERT INTO test(val, previousval) VALUES
(100, (SELECT val FROM test ORDER BY id DESC LIMIT 1));
INSERT INTO test(val, previousval) VALUES       
(200, (SELECT val FROM test ORDER BY id DESC LIMIT 1));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM