Take a snapshot for a table in oracle - oracle

I have a table called "col" - This table is updated every month.
what i want is to take snapshot (updated version) for that table every period of time.
my question is how to take snapshot for that table in oracle ?
EDIT: my DB version is 19c

The easiest way is to just run a "CTAS" aka "CREATE TABLE [your table name plus some date string] AS SELECT * FROM [the table];
CREATE TABLE [SNAPSHOT NAME] as SELECT * FROM [TABLE NAME];
Note: this works a lot of places, not just in Oracle.

Create the SNAPSHOT TABLE with an identical structure as the original column with an additional column SNAPSHOT_DATE
Example
CREATE TABLE COL_SNAPSHOT AS
SELECT
cast (null as DATE) as SNAPSHOT_DATE,
a.*
from COL a
WHERE 1=0;
THis statement creates an e,pty table with the additional column. You may partition the table an the column SNAPSHOT_DATEif you are lincenced for it.
Now once a month you take a new snapshot using following insert
INSERT INTO COL_SNAPSHOT
(SNAPSHOT_DATE, ... all columns from COL ...)
SELECT
sysdate SNAPSHOT_DATE, ... all columns from COL ...
FROM COL;
You save the current state of the table and additionaly in the column SNAPSHOT_DATE is the timestamp of the snapshot.

Related

oracle how to alter table add partition by range interval

i have searched a lot but i have found nothing about how to
add a range partition to an existing table
alter table myuser.mytable
add PARTITION BY RANGE (mynumber) INTERVAL (1)
( PARTITION p1 VALUES LESS THAN (108))
that gives me ORA:14150 error, SUBPARTITON keyword is missing,
but i dont want to give subpartition
EDIT: On 19c and 12cR2 this can be done using the MODIFY Clause of ALTER TABLE
ALTER TABLE myuser.mytable MODIFY
PARTITION BY RANGE (mynumber) INTERVAL (1)
( PARTITION p1 VALUES LESS THAN (108)
PARTITION p2 VALUES LESS THAN (109))
ONLINE
UPDATE INDEXES
See this from Oracle Docs
PRIOR To 19c or 12cR2:
If your existing Table is Non-Partitioned you will have to:
CREATE a new TABLE with partition definitions. Lets call this table MYTABLE_NEW
INSERT into MYTABLE_NEW all data from MYTABLE
RENAME MYTABLE to MYTABLE_OLD
RENAME MYTABLE_NEW to MYTABLE
DROP MYTABLE_OLD
OR
dbms_redefinition can also be used
See this from AskTom
Also see this other Answer

Is there any major performance issues if I use virtual columns in Oracle?

Is there any major performance issues if I use virtual columns in an Oracle table?
We have a scenario where the db has fields stored as strings. Since other production apps run off those fields we can't easily convert them.
I am tasked with generating reports from the same db. Since I need to be able to filter by dates (which are stored as strings) it was brought to my attention that we could create a virtual date field so that I can query against that.
Has anyone ran into any roadblocks with this approach?
A virtual column is defined using an expression that is evaluated when you select from the table. There is no performance hit on inserts/updates on the table.
For example:
create table t1 (
datestr varchar2(100),
datedt date generated always as (to_date(datestr,'YYYYMMDD'))
);
Table created.
SQL> insert into t1 (datestr) values ('20160815');
1 row created.
SQL> insert into t1 (datestr) values ('xxx');
1 row created.
SQL> commit;
Commit complete.
Note that I was able to insert an invalid date value into datestr. Now we can try to select the data:
SQL> select * from t1 where datedt = date '2016-08-15';
ERROR:
ORA-01841: (full) year must be between -4713 and +9999, and not be 0
This could be a problem for you if you can't guarantee all the strings hold valid dates.
As for performance, when you run the above query what you are really running is:
select * from t1 where to_date(datestr,'YYYYMMDD') = date '2016-08-15';
So the query will not be able to use an index on the datestr column (probably), and you may want to add an index on the virtual column. Again, this won't work if any of the strings don't contain valid dates.
Another consideration is potential impact on existing code. Hopefully you won't have any code like insert into t1 values (...); i.e. not specifying the column list. If you do you will get the error:
ORA-54013: INSERT operation disallowed on virtual columns

How to modify data type in Oracle with existing rows in table

How can I change DATA TYPE of a column from number to varchar2 without deleting the table data?
You can't.
You can, however, create a new column with the new data type, migrate the data, drop the old column, and rename the new column. Something like
ALTER TABLE table_name
ADD( new_column_name varchar2(10) );
UPDATE table_name
SET new_column_name = to_char(old_column_name, <<some format>>);
ALTER TABLE table_name
DROP COLUMN old_column_name;
ALTER TABLE table_name
RENAME COLUMN new_column_name TO old_coulumn_name;
If you have code that depends on the position of the column in the table (which you really shouldn't have), you could rename the table and create a view on the table with the original name of the table that exposes the columns in the order your code expects until you can fix that buggy code.
You have to first deal with the existing rows before you modify the column DATA TYPE.
You could do the following steps:
Add the new column with a new name.
Update the new column from old column.
Drop the old column.
Rename the new column with the old column name.
For example,
alter table t add (col_new varchar2(50));
update t set col_new = to_char(col_old);
alter table t drop column col_old cascade constraints;
alter table t rename column col_new to col_old;
Make sure you re-create any required indexes which you had.
You could also try the CTAS approach, i.e. create table as select. But, the above is safe and preferrable.
The most efficient way is probably to do a CREATE TABLE ... AS SELECT
(CTAS)
alter table table_name modify (column_name VARCHAR2(255));
Since we can't change data type of a column with values, the approach that I was followed as below,
Say the column name you want to change type is 'A' and this can be achieved with SQL developer.
First sort table data by other column (ex: datetime).
Next copy the values of column 'A' and paste to excel file.
Delete values of the column 'A' an commit.
Change the data type and commit.
Again sort table data by previously used column (ex: datetime).
Then paste copied data from excel and commit.

SQL Server - Date of newly inserted column in a table

As part of my project, new columns are introduced in many tables. I wanted to find out the date in which this columns are introduced. Is there a way I can query the date of insertion of all the columns in a specific table in Oracle SQL Developer 3.0.04.
You can try to use the last_ddl_time object from the dba_objects table.

Automatically populate date in oracle table

I have created a table in oracle XE, and I have a field with type date. I would like if possible when I insert a row, that it automatically fills that field with the current date from the system.
I am inserting the rows from the SQL prompt.
Thanks
Here is how, you need to format your table properly:
create table test (first number
, second timestamp default systimestamp
, third varchar2(12));
And your default value is always current system time formatted as timestamp.
change the field after creating the table
ALTER TABLE table MODIFY time_collumn TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
Or you could also use a trigger:
CREATE OR REPLACE TRIGGER date_trigger
BEFORE INSERT
ON table_name
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT sysdate INTO :NEW.column_name FROM dual;
END;
The below snippet might be helpful if we forget to add the constraint while creating the table:
ALTER TABLE TABLE_NAME
ADD CONSTRAINT CONSTRAINT_NAME
COLUMN_NAME DATA_TYPE DEFAULT CURRENT_DATE;

Resources