我知道一种可行的方法,但它有点难看。它依赖于精心构建的约束和对数据库的播种。为简洁起见,我只使用了 5 行而不是 50 行。
create table test (
row_num integer primary key
check ((round(row_num) = row_num) and (row_num between 1 and 5)),
other_columns char(1) not null default 'x',
row_timestamp timestamp
not null unique
default current_timestamp
);
表达式round(row_num = row_num) 保证row_num 列中有整数。否则,SQLite 会让你在其中插入 1.54 或 'wibble'。
other_columns 列只是您的实际数据的占位符。
insert into test (row_num, row_timestamp) values
(1, '2015-01-01 08:00:01'),
(2, '2015-01-01 08:00:02'),
(3, '2015-01-01 08:00:03'),
(4, '2015-01-01 08:00:04'),
(5, '2015-01-01 08:00:05');
实际的时间戳值并没有任何意义。反正还没有。像这样播种数据库意味着,从现在开始,您只需执行更新语句。如果表一开始是空的,则您必须处理不同的插入和更新逻辑。例如,您必须计算行数才能确定是插入还是更新。
create trigger update_timestamp
after update on test
for each row
begin
update test
set row_timestamp = strftime('%Y-%m-%d %H:%M:%f', 'now')
where row_num = OLD.row_num;
end;
“update_timestamp”触发器使 SQLite 将时间戳保持在几分之一秒内 (%f)。可能取决于底层操作系统是否支持小数精度。
create trigger no_deletes
after delete on test
for each row
begin
-- There might be a more elegant way to prevent deletes.
-- This way just inserts exactly what a delete statement deletes.
insert into test (row_num, other_columns, row_timestamp)
values (OLD.row_num, OLD.other_columns, OLD.row_timestamp);
end;
现在您可以更新数据了。您更新自己的数据,这里只是占位符
other_columns,其余的由 SQLite 处理。
update test
set other_columns = 'b'
where row_timestamp = (select min(row_timestamp) from test);
select * from test order by row_timestamp desc;
row_num other_columns row_timestamp
---------- ------------- -----------
1 b 2015-03-08 12:43:21.926
5 x 2015-01-01 08:00:05
4 x 2015-01-01 08:00:04
3 x 2015-01-01 08:00:03
2 x 2015-01-01 08:00:02