SQLite: bulk field update without cursor

I have the following table:

CREATE TABLE Records (
RecordIndex INTEGER NOT NULL,
...
Some other fields
...
Status1 INTEGER NOT NULL,
Status2 INTEGER NOT NULL,
UpdateDate DATETIME NOT NULL,
CONSTRAINT PK_Records PRIMARY KEY (RecordIndex ASC))

And the index:

CREATE INDEX IDX_Records_Status ON ClientRecords
  (Status1 ASC, Status2 ASC, RecordIndex ASC)

I need to get records of a certain state one by one, so I used this operator:

SELECT *
FROM RECORDS
WHERE RecordIndex > @PreviousIndex
AND Status1 = @Status1
AND Status2 = @Status2
LIMIT 1

But now I need to get records sorted by another field, but this field is not unique for each record, so I can not use it in the same way. So I decided to add a new SortIndex field to my table.

Since there are no cursors in SQLite, I do the following to initialize the values ​​for SortIndex.
First I create a temporary table:

CREATE TEMP TABLE Sort (
SortIdx INTEGER PRIMARY KEY AUTOINCREMENT,
RecordIdx INTEGER )

Then I populate this table in the correct sort order:

INSERT INTO Sort
  SELECT NULL, RecordIndex
  FROM Records
  ORDER BY SomeField ASC, RecordIndex ASC

Then I create an index in the temporary table:

CREATE INDEX IDX_Sort_RecordIdx ON Sort (RecordIdx ASC)

Then I update the SortIndex field in the records table:

UPDATE Records
SET SortIndex =
  (SELECT SortIdx
   FROM Sort
   WHERE RecordIdx = RecordIndex)

Then I drop the temporary table:

DROP TABLE Sort

And finally, I create a new index in the records table

CREATE INDEX IDX_Records_Sort ON Records
  (Status1 ASC, Status2 ASC, SortIndex ASC)

SELECT *
FROM Records
WHERE SortIndex > @PreviousSortIndex
AND Status1 = @Status1
AND Status2 = @Status2
LIMIT 1

, , 500 . , 2 . , SortIndex , SQLite : (

?

!

+3
2

UPDATE INSERT OR REPLACE SQLite, UPDATE , :

UPDATE Records
   SET SortIndex =
       (SELECT SortIdx
          FROM Sort
         WHERE RecordIdx = RecordIndex) 

INSERT OR REPLACE INTO Records (RecordIndex, SortIndex, ...)
SELECT RecordIndex, SortIdx, ... FROM another_temporary_table_containing_all_columns.

, , , , SELECT, : SQLite

CREATE TABLE original (id INTEGER PRIMARY KEY, content TEXT);

BEGIN TRANSACTION;
INSERT INTO original(id, content) VALUES(1, 'foo');
INSERT INTO original(id, content) VALUES(2, 'bar');
INSERT INTO original(id, content) VALUES(3, 'baz');
COMMIT TRANSACTION;

CREATE TABLE id_remap(old_id INTEGER, new_id INTEGER);

BEGIN TRANSACTION;
INSERT INTO id_remap(old_id, new_id) VALUES(2,3);
INSERT INTO id_remap(old_id, new_id) VALUES(3,2);
COMMIT TRANSACTION;

INSERT OR REPLACE INTO original (id, content)
SELECT b.new_id, a.content
  FROM original a
 INNER JOIN id_remap b
    ON b.old_id = a.id;

SELECT * FROM original;

:

1|foo
2|baz
3|bar

, , , INSTEAD OF UPDATE . , , . , , .

SQLite:

CREATE TABLE original (id INTEGER PRIMARY KEY, content TEXT);

BEGIN TRANSACTION;
INSERT INTO original(id, content) VALUES(1, 'foo');
INSERT INTO original(id, content) VALUES(2, 'bar');
INSERT INTO original(id, content) VALUES(3, 'baz');
COMMIT TRANSACTION;

CREATE TABLE id_remap(old_id INTEGER, new_id INTEGER);

BEGIN TRANSACTION;
INSERT INTO id_remap(old_id, new_id) VALUES(3,6);
COMMIT TRANSACTION;

CREATE TEMPORARY VIEW tmp_id_mapping
    AS
SELECT a.content, b.old_id, b.new_id
  FROM original a
 INNER JOIN id_remap b
    ON b.old_id = a.id;

 CREATE TEMPORARY TRIGGER IF NOT EXISTS tmp_trig_id_remap
INSTEAD OF UPDATE OF content ON tmp_id_mapping
    FOR EACH ROW
  BEGIN
    UPDATE original
       SET id = new.new_id
     WHERE id = new.old_id;
   END;

UPDATE tmp_id_mapping
   SET content = 'hello';

SELECT * FROM original;

:

1|foo
2|bar
6|baz
+1

, SQLlite ~ 500k ( ).

, - .


, , , , .

DMBS - , , , , .

- .

, , - .

sqlite, ., .


SQL

-- init
CREATE TABLE IF NOT EXISTS `records` (
  `RecordID` int(10) default NULL,
  `Status` int(10) default NULL,
  `SomeField` char(50) default NULL,
  `RecordIndex` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

truncate `records`;
INSERT INTO `records` (`RecordID`, `Status`, `SomeField`, `RecordIndex`) VALUES
    (1, 1, 'a', 35),
    (2, 1, 'b', 20),
    (3, 1, 'c', 42);

-- 1st select
SELECT * FROM records WHERE Status = 1 ORDER BY SomeField ASC, RecordIndex ASC LIMIT 1 OFFSET 0;

-- update
update records set `Status` = 2 where RecordID = 1;

-- select next
SELECT * FROM records WHERE Status = 1 ORDER BY SomeField ASC, RecordIndex ASC LIMIT 1 OFFSET 1;
0

All Articles