Determine if row has ever been updated - sql

Might be a long shot, but I'm looking for a way to see if a row has ever been updated since it was inserted.
Ex.
CREATE TABLE TEST_DATA AS
( SELECT 'A' AS dummy
FROM dual
UNION
SELECT 'B' AS dummy
FROM dual
);
UPDATE TEST_DATA
SET dummy = 'C'
WHERE dummy = 'B';
Is there any way I can tell that the 'C' record has been updated?
Also, I have absolutely no control over the data model so I can't add an add timestamp and an update timestamp to the actual table.

this will work:
create table test_data(a varchar(1));
insert into test_data values('A');
insert into test_data values('B');
insert into test_data values('C');
insert into test_data values('D');
select * from test_data;
A
B
C
D
create table noofchanges(data varchar(1),numberofchanges int) ;
insert into noofchanges(data,numberofchanges) select a,0 from test_data;
select * from noofchanges;
A 0
B 0
C 0
D 0
CREATE OR REPLACE TRIGGER test_data_before_update
BEFORE UPDATE
ON test_data
FOR EACH ROW
BEGIN
update noofchanges
set numberofchanges=numberofchanges+1
where data=:old.a;
END;
update test_data set a='A' where a='B';
select * from test_data;
A
A
C
D
select * from noofchanges
A 0
B 1
C 0
D 0
thank you!!!!!!

Related

How to store fetched bulk values into single variable and insert all values it on one variable using pl/sql

Note
Somebody Tell me how to store Multiples rows value for a single column store into a single variable and behalf of that variable returned values store in table on one single click how to do such scenario using pl/sql.
Like Such Query Return single column with Multi rows i want to store it into some var and insert all values on single click process.It will generate error image of error has attached
DECLARE
l_respondent_id VARCHAR(100);
BEGIN
FOR c IN (
SELECT
s.gr_number
FROM
student s
LEFT JOIN class_time ct ON ct.class_id = s.class_id
AND instr(s.class_time, ct.class_time) > 0
WHERE
upper(TRIM(ct.class_id)) = upper(TRIM(:app_user))
AND s.gr_number IS NOT NULL
AND is_active_flg = 'Y'
) LOOP
l_respondent_id := c.gr_number;
BEGIN
SELECT
s.gr_number
INTO l_respondent_id
FROM
student s
LEFT JOIN class_time ct ON ct.class_id = s.class_id
AND instr(s.class_time, ct.class_time) > 0
WHERE
upper(TRIM(ct.class_id)) = upper(TRIM(:app_user))
AND s.gr_number IS NOT NULL
AND is_active_flg = 'Y'
AND s.gr_number = c.gr_number;
EXCEPTION
WHEN no_data_found THEN
l_respondent_id := NULL;
END;
IF l_respondent_id IS NULL THEN
INSERT INTO student_class_attend ( gr_number ) VALUES ( c.gr_number ) RETURNING gr_number INTO l_respondent_id;
END IF;
END LOOP;
END;
You can probably use a nested table for this, together with a BULK COLLECT and a FORALL. Simplified example:
Tables and data
create table students( id primary key, fname, lname )
as
select 1, 'fname_1', 'lname_1' from dual union all
select 2, 'fname_2', 'lname_2' from dual union all
select 3, 'fname_3', 'lname_3' from dual union all
select 4, 'fname_4', 'lname_4' from dual union all
select 5, 'fname_5', 'lname_5' from dual union all
select 6, 'fname_6', 'lname_6' from dual ;
-- empty
create table attendance( studentid number references students, when_ date ) ;
Anonymous block
declare
-- This will allow you to store several studentIDs:
type studentid_t is table of students.id%type index by pls_integer ;
-- The current attendance list. Notice the TYPE.
attendancelist studentid_t ;
begin
-- Your query (including all the necessary joins and conditions) here.
-- In this case, we will pick up 3 of the 6 IDs.
select id bulk collect into attendancelist
from students
where mod( id, 2 ) = 0 ;
-- Write a _single_ DML statement after FORALL (which is not a loop - see docs)
forall i in attendancelist.first .. attendancelist.last
insert into attendance( studentid, when_ )
values( attendancelist( i ) , sysdate ) ; -- use whatever you need here
end ;
/
Result (after executing the anonymous block)
SQL> select * from attendance ;
STUDENTID WHEN_
---------- ---------
2 07-JUN-20
4 07-JUN-20
6 07-JUN-20
DBfiddle here.

update and insert into table in with single query

table 1
id pk1 timestamp
1 a 10-jul-2019
2 h 11-mar-2019
3 k 19-jul-2019
4 j 7-n0v-2018
5 h 11-jul-2019
table 2
col start_date end_date
a 10-jul-2019
h 11-mar-2019 11-jul-2019
k 19-jul-2019
j 7-nov-2018
h 11-jul-2019
Q:> I want this process to be repeat after equal interval of time.
if a new value got enter into the table 1 then same value should enter into the table 2 but if existing values enters in table 1 then just update end date of previous same value of table 2 and add one new value with null end date into table 2 (example value H in table 1 and table 2).
we need to use only single query.
with merge we are not able to get this
if a new value got enter into the table 1 then same value should enter
into the table 2 but if existing values enters in table 1 then just
update end date of previous same value of table 2 and add one new
value with null end date into table 2
Your scenario need a Trigger to be created on Table1. You can put down your logic to update Table2 in the Trigger.
See below demo:
--Table1 DDL
Create table tab1 (
id number,
pk1 varchar(1),
time_stamp date
);
--Table2 DDL
create table tab2 (
col varchar(1),
start_date date,
end_date date
);
Here is Trigger on Table1
Create or replace trigger t1
before insert on tab1
for each row
begin
DECLARE
l_exists INTEGER;
BEGIN
SELECT COUNT(*)
INTO l_exists
FROM tab2
WHERE col = :new.pk1 ;
IF l_exists = 0
THEN
INSERT INTO TAB2
values
(:new.pk1,:new.time_stamp,null);
ELSE
Update tab2
set end_date = :new.time_stamp
where col = :new.pk1;
INSERT INTO TAB2
values
(:new.pk1,:new.time_stamp,null);
END IF;
END;
end;
--Execution:
insert into tab1 values (1,'a',to_date('10-jul-2019','DD-MON-YYYY'));
insert into tab1 values (2,'h',to_date('11-mar-2019','DD-MON-YYYY'));
insert into tab1 values (3,'k',to_date('19-jul-2019','DD-MON-YYYY'));
insert into tab1 values (4,'j',to_date('07-nov-2019','DD-MON-YYYY'));
insert into tab1 values (5,'h',to_date('11-jul-2019','DD-MON-YYYY'));
Commit;
SQL> select * from tab1;
ID P TIME_STAM
---------- - ---------
1 a 10-JUL-19
3 k 19-JUL-19
4 j 07-NOV-19
2 h 11-MAR-19
5 h 11-JUL-19
SQL> select * from tab2;
C START_DAT END_DATE
- --------- ---------
a 10-JUL-19
k 19-JUL-19
j 07-NOV-19
h 11-MAR-19 11-JUL-19
h 11-JUL-19

How to validate data after update in oracle

I have two tables A and B which are not related.
SQL> select * from A;
OLD_ID R_ID
---------- ----------
TA-BC 1
TB-BC 2
TC-BC 3
TD-BC 4
TE-BC 5
TF-BC 6
TG-BC 7
8
SQL> select * from B;
NEW_ID OLD_ID S_CD
---------- ---------- -----
1 TA-BC A
2 TB-BC B
3 TC-BC C
4 TD-BC A
5 TE-BC B
6 TF-BC F
7 TG-BC C
8 TH-BC B
I need to update column "old_id" in table A with corresponding "new_id" values from table B where A.OLD_ID = B.OLD_ID.
I have written something like below. The data in table A and B has around 1 million records the one i gave above here is sample data. Since the data volume is high am updating for every 25k records and commiting it in a loop.
DECLARE
v_cnt number := 1;
BEGIN
WHILE v_cnt > 0 LOOP
UPDATE /*+ parallel(A 10) */ A a
SET a.old_id =
(SELECT DISTINCT new_id
FROM B b
WHERE b.old_id = a.old_id)
WHERE EXISTS
(SELECT 1
FROM B b1
WHERE b1.old_id = a.old_id and ROWNUM < 25000;
v_cnt := SQL%ROWCOUNT;
COMMIT;
END LOOP;
END;
/
I would like to know how can i print how many records got updated and how can i validate whether all the records in table A which has the matching record in table B with old_id has got updated correctly or not. What is the query i can write before/after the update statement to validate if table A "old_id" column has been updated correctly with values from table B "new_id" columns
Below is the table creation script.
create table A(old_id varchar2(10),r_id number);
insert into A values ('TA-BC',1);
insert into A values ('TB-BC',2);
insert into A values ('TC-BC',3);
insert into A values ('TD-BC',4);
insert into A values ('TE-BC',5);
insert into A values ('TF-BC',6);
insert into A values ('TG-BC',7);
insert into A(r_id) values(8);
commit;
create table B(new_id number,old_id varchar2(10),s_cd varchar2(5));
insert into B values (1,'TA-BC','A');
insert into B values (2,'TB-BC','B');
insert into B values (3,'TC-BC','C');
insert into B values (4,'TD-BC','A');
insert into B values (5,'TE-BC','B');
insert into B values (6,'TF-BC','F');
insert into B values (7,'TG-BC','C');
insert into B values (8,'TH-BC','B');
commit;
I don't see why you are replacing OLD_ID with NEW_ID when they are different data types: OLD_ID is char and NEW_ID is an integer.
It would be better to add a new field (column) to the table to store NEW_ID and update that.
You can then check the mapping of old to new has been performed correctly and take advantage of the fact the new id is the correct data type for joins to other tables using NEW_ID

Insert 1000 rows in single sql statment or procedure

How should i write a single sql statement or a stored procedure,
To insert 1000 values in 1000 rows and same column with each column having different values (among those 1000)
Here is the query i wrote,
INSERT INTO a_b values
(
(SELECT max(a_b_id) + 1 from a_b),
1111,
(SELECT s_id FROM a_b WHERE s_id in ('0','1','2','3','4')),
0,
1,
sysdate,
sysdate,
0,
1,
null
);
like say, i have 1000 s_id's i want select them one by one and insert them in one particular column, each time creating a new row.
EX, in first row s_id should be 0 then in second row it should be 1 like that goes on till thousand, attached an image of sample database i am working with.
You can use connect by for this:
INSERT INTO a_b (s_id, col2, col3, ....)
select level, --<< this value will change for every row
1111,
sysdate,
... more columns ...
from dual
connect by level <= 1000;
you can use cross apply to get 1000 rows along with 1000 other columns to insert 1000 rows as below:
insert into a_b (column names...)
select (max(a_b_id) over()) +1 as MaxId, s_id from a_b a cross apply (select 0, 1,SYSDATETIME, SYSDATETIME, 0, 1, null) b where a.s_id('111','222')--condition
The below is a syntax error. You will never get something like that to work.
create table fff
( id int not null
);
insert fff values (select 1,7777,select 3, select 3);
So you need to break it up into chunks
DROP PROCEDURE IF EXISTS uspRunMe;
DELIMITER $$
CREATE PROCEDURE uspRunMe()
BEGIN
insert into a_b select max(a_b_id) + 1 from a_b;
insert into a_b values (1111);
insert into a_b SELECT s_id FROM a_b WHERE s_id in ('0','1','2','3','4');
insert into a_b values (0,1);
insert into a_b select sysdate,sysdate;
insert into a_b values (0,1,null);
END;$$
DELIMITER ;
Test it:
call uspRunMe();
The above is for MySQL. You have a few db engines tagged here.

Oracle MERGE does not INSERT

I have this simple example I can't seems to get working :
MERGE INTO mytable mt
USING dual
ON (mt.id = 'AAA' )
WHEN MATCHED THEN
UPDATE SET mt.name = 'updated'
WHEN NOT MATCHED THEN
INSERT (mt.id , mt.name )
VALUES ('AAA', 'Gooood' );
If a 'AAA' record exists in the table, it is updated successfully.
But if does not exists, it is not inserted :
Affected rows: 0
Time: 0.003ms
Any clue on what I am doing wrong ?
Works for me:
SQL> create table mytable (id varchar(3), name varchar(30));
Table created.
SQL> MERGE INTO mytable mt
2 USING dual
3 ON (mt.id = 'AAA' )
4 WHEN MATCHED THEN
5 UPDATE SET mt.name = 'updated'
6 WHEN NOT MATCHED THEN
7 INSERT (mt.id , mt.name )
8 VALUES ('AAA', 'Gooood' );
1 row merged.
SQL> select * from mytable;
ID NAME
--- ------------------------------
AAA Gooood