Sqlite INSERT OR REPLACE is incrementing rowid - sqlite

I am using the INSERT OR REPLACE syntax to either insert or update a row that may exist based on a unique column constraint within the table.
The table structure is
| Name | Age | CustomerId (unique) |
When I print out the table the first time, I get something like
| Name | Age | CustomerId | rowid |
|"Bob" | 22 | 5 | 1 |
Then I run INSERT OR REPLACE INTO MyTable(Name, Age, CustomerId) VALUES ("Bob", 23, 5);"
Without fail, this will increment the rowid column each time it is run. So now the result is
| Name | Age | CustomerId | rowid |
|"Bob" | 23 | 5 | 2 |
How do I prevent rowid from incrementing?

This is how INSERT OR REPLACE works.
If a violation of a unique index/constraint occurs then the existing row is deleted and the new row is inserted, so a new rowid is assigned for the new row.
If you don't want this to happen you must use UPSERT:
insert into tablename(Name, Age, CustomerId) values ('Bob', 23, 5)
on conflict(CustomerId) do update
set Name = excluded.Name,
Age = excluded.Age;
See the demo.

Related

How to select the next 50 records from a specified row in an SQLite table

Consider that my SQLite table has the following schema,
|'''''''''''''''''''''''''''''''''''''
| unique_id(TXT) | object_data(BLOB) |
|'''''''''''''''''''''''''''''''''''''
| | |
| | |
| | |
''''''''''''''''''''''''''''''''''''''
Assume that the row_id property is enabled, and so my question is, for a given unique_id, is it possible to fetch the next 50 records from the table,
using a single SQL query? (Using the row_id property)
Try getting result through this method.
Select * from table_name [WHERE conditions] Limit 50 offset (Select row_id from table_name where unique_id = x);

Sqlite: Insert new record by copying from old entry when inserting in the ID field

I want to create a duplicated entry when I insert a new record with an existing id number.
i.e. when I enter a new row with 2 in the ID field, it will automatically create a new entry by copying all the fields from the row with ID=2
I am using the below trigger but it is not working.
1) the trigger fails to work when inserting an existing number in the ID column
2) when I changed new.ID to other field like new.col_2, the trigger works but an extra entry is also created after the trigger which I don't want it.
How can I solve these two issues or are there any workarounds for them?
Thanks.
CREATE TRIGGER "main"."NewTrigger" BEFORE INSERT ON "record" FOR EACH ROW WHEN new.ID is not NULL
BEGIN
INSERT INTO record (col_1, col_2)
SELECT col_1, col_2 FROM record
WHERE ID = new.ID;
END;
e.g.
original table named "record"
ID | col_1 | col_2
1 | Ada | 20
2 | Ben | 56
3 | Candy | 82
when I insert a new entry like this:
ID | col_1 | col_2
2
the resulting table "record" will become:
ID | col_1 | col_2
1 | Ada | 20
2 | Ben | 56
3 | Candy | 82
4 | Ben | 56
The INSERT statements inserts a new row.
This is not what you want because you are already inserting a row.
What you need to do is to change the values in the row after it has been inserted:
CREATE TRIGGER NewTrigger
AFTER INSERT ON record
FOR EACH ROW
WHEN NEW.ID IS NOT NULL AND NEW.Col1 IS NULL
BEGIN
UPDATE record
SET (Col1, Col2) = (SELECT Col1, Col2
FROM record
WHERE ID = NEW.ID
AND Col1 IS NOT NULL);
WHERE ID = NEW.ID
AND Col1 IS NULL;
END;
(Using a row value requires SQLite 3.15.0 or later.)

How to get ID from table A to table B in trigger?

I have two tables, A & B:
TABLE A
id | name
TABLE B
id | name | fk_idA
I want to create trigger AFTER INSERT in TABLE B which updates fk_idA appropriate with the newest id from table A.
An example:
TABLE A
id | name
1 | Andrew
2 | David
TABLE B
id | name | fk_idA
1 | Photo1 | 2
If the ID column is autoincrementing, the latest is the largest one, i.e., the one returned by MAX:
CREATE TRIGGER DefaultAIsLatest
AFTER INSERT ON TableB
FOR EACH ROW
WHEN NEW.fk_idA IS NULL
BEGIN
UPDATE TableB
SET fk_idA = (SELECT MAX(id)
FROM TableA)
WHERE id = NEW.id;
END;

selecting a row based on a number of column values in SQLite

I have a table with this structure:
id | IDs | Name | Type
1 | 10 | A | 1
2 | 11 | B | 1
3 | 12 | C | 2
4 | 13 | D | 3
except id nothing else is a FOREIGN or PRIMARY KEY. I want to select a row based on it's column values that are not PRIMARY KEY. I have tried the following syntax but it yields no results.
SELECT * FROM MyTable WHERE Name = 'A', Type = 1;
what am I doing wrong? What is exactly returned by a SELECT statement? I'm totally new to Data Base and I'm currently experimenting and trying to learn it. so far my search has not yield any results regarding this case.
Use and to add multiple conditions to your query
SELECT *
FROM MyTable
WHERE Name = 'A'
AND Type = 1;

How to add a new column in a View in sqlite?

I have this database in sqlite (table1):
+-----+-------+-------+
| _id | name | level |
+-----+-------+-------+
| 1 | Mike | 3 |
| 2 | John | 2 |
| 3 | Bob | 2 |
| 4 | David | 1 |
| 5 | Tom | 2 |
+-----+-------+-------+
I want to create a view with all elements of level 2 and then to add a new column indicating the order of the row in the new table. That is, I would want this result:
+-------+------+
| index | name |
+-------+------+
| 1 | John |
| 2 | Bob |
| 3 | Tom |
+-------+------+
I have tried:
CREATE VIEW words AS SELECT _id as index, name FROM table1;
But then I get:
+-------+------+
| index | name |
+-------+------+
| 2 | John |
| 3 | Bob |
| 5 | Tom |
+-------+------+
I suppose it should be something as:
CREATE VIEW words AS SELECT XXXX as index, name FROM table 1;
What should I use instead of XXXX?
When ordered by _id, the number of rows up to and including this one is the same as the number of rows where the _id value is less than or equal to this row's _id:
CREATE VIEW words AS
SELECT (SELECT COUNT(*)
FROM table1 b
WHERE level = 2
AND b._id <= a._id) AS "index",
name
FROM table1 a
WHERE level = 2;
(The computation itself does not actually require ORDER BY _id because the order of the rows does not matter when we're just counting them.)
Please note that words is not guaranteed to be sorted; add ORDER BY "index" if needed.
And this is, of course, not very efficient.
You have two options. First, you could simply add a new column with the following:
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
Second, and more complicatedly, but would actually put the column where you want it, would be to rename the table:
ALTER TABLE {tableName} RENAME TO TempOldTable;
Then create the new table with the missing column:
CREATE TABLE {tableName} (name TEXT, COLNew {type} DEFAULT {defaultValue}, qty INTEGER, rate REAL);
And populate it with the old data:
INSERT INTO {tableName} (name, qty, rate) SELECT name, qty, rate FROM TempOldTable;
Then delete the old table:
DROP TABLE TempOldTable;
I'd much prefer the second option, as it will allow you to completely rename everything if need be.

Resources