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

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;

Related

Sqlite INSERT OR REPLACE is incrementing rowid

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.

SQLite - Merge 2 tables according to modified date, insert a new row if necessary

I have a table having an ID column, this column is a primary key and unique as well. In addition, the table has a modified date column.
I have the same table in 2 databases and I am looking to merge both into one database. The merging scenario in a table is as follows:
Insert the record if the ID is not present;
If the ID exists, only update if the modified date is greater than that of the existing row.
For example, having:
Table 1:
id | name | createdAt | modifiedAt
---|------|------------|-----------
1 | john | 2019-01-01 | 2019-05-01
2 | jane | 2019-01-01 | 2019-04-03
Table 2:
id | name | createdAt | modifiedAt
---|------|------------|-----------
1 | john | 2019-01-01 | 2019-04-30
2 | JANE | 2019-01-01 | 2019-04-04
3 | doe | 2019-01-01 | 2019-05-01
The resulting table would be:
id | name | createdAt | modifiedAt
---|------|------------|-----------
1 | john | 2019-01-01 | 2019-05-01
2 | JANE | 2019-01-01 | 2019-04-04
3 | doe | 2019-01-01 | 2019-05-01
I've read about INSERT OR REPLACE, but I couldn't figure out how the date condition can be applied. I know as well that I can loop through each pair of similar row and check the date manually but this would be very time and performance consuming. Therefore, is there an efficient way to accomplish this in SQLite?
I'm using sqlite3 on Node.js .
The UPSERT notation added in Sqlite 3.24 makes this easy:
INSERT INTO table1(id, name, createdAt, modifiedAt)
SELECT id, name, createdAt, modifiedAt FROM table2 WHERE true
ON CONFLICT(id) DO UPDATE
SET (name, createdAt, modifiedAt) = (excluded.name, excluded.createdAt, excluded.modifiedAt)
WHERE excluded.modifiedAt > modifiedAt;
First create the table Table3:
CREATE TABLE Table3 (
id INTEGER,
name TEXT,
createdat TEXT,
modifiedat TEXT,
PRIMARY KEY(id)
);
and then insert the rows like this:
insert into table3 (id, name, createdat, modifiedat)
select id, name, createdat, modifiedat from (
select * from table1 t1
where not exists (
select 1 from table2 t2
where t2.id = t1.id and t2.modifiedat >= t1.modifiedat
)
union all
select * from table2 t2
where not exists (
select 1 from table1 t1
where t1.id = t2.id and t1.modifiedat > t2.modifiedat
)
)
This uses a UNION ALL for the 2 tables and gets only the needed rows with EXISTS which is a very efficient way to check the condition you want.
I have >= instead of > in the WHERE clause for Table1 in case the 2 tables have a row with the same id and the same modifiedat values.
In this case the row from Table2 will be inserted.
If you want to merge the 2 tables in Table1 you can use REPLACE:
replace into table1 (id, name, createdat, modifiedat)
select id, name, createdat, modifiedat
from table2 t2
where
not exists (
select 1 from table1 t1
where (t1.id = t2.id and t1.modifiedat > t2.modifiedat)
)

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.)

Table name in another table using PostgreSQL

I have one table in which I have name of all the tables.
Table
ID | Name | table_name|
1 | A | abc
2 | B | xyz
3 | C | 123
Now I have tables abc, xyz and 123 on the basis of name I want to get the table name and then from that table I want it complete data
SELECT *
FROM (SELECT table_name FROM Table 1 WHERE Table1.Name = 'A')
This query is not working in PostgreSQL
Please try after modifying the query as follows:
SELECT *
FROM (SELECT table_name FROM Table 1 WHERE Table1.Name = 'A') As TblName

UPDATE multiple rows using SELECT

I have A table and two rows with id=1 and id=2 and their x parameter is 1. I also have B table and two rows with same id 1 and 2. I am trying to update all of the data(column)on B table which has same id with A table whose x parameter is 1.
A table
id | x |
1 | 1 |
2 | 1 |
B table
id | Y |
1 | yes|
2 | yes|
My query is
UPDATE B SET y='No' WHERE B.id=(SELECT A.id FROM A WHERE A.x=1);
The problem is select returns mutliple data and i can only update the first data.
I tried to use JOIN but sqlite gives syntax error near INNER i couldn't find the problem.
UPDATE B SET B.y='No' INNER JOIN A ON B.id=A.id WHERE A.x=1;
Use this:
UPDATE ... WHERE B.id IN (SELECT A.id ...);

Resources