Oracle can use computed aggregrates and joins from materialized views to improve performance on a database query by rewriting a query against the warehouse to make use of the view. To allow this to happen the view must support query rewrite and the warehouse itself must support query rewrite. Be aware that the materialized view must be fresh, or the related integrity session parameters relaxed to allow the rewrite to happen.
To enable query rewrite on the view do
CREATE MATERIALIZED VIEW my_view_mv
ENABLE QUERY REWRITE AS
SELECT .....
To enable query rewrite ensure QUERY_REWRITE_ENABLED = TRUE for the session or the system.
Basic query rewrite documentation for Oracle 11g R2
http://docs.oracle.com/cd/E11882_01/server.112/e25554/qrbasic.htm
Advanced query rewrite documentation for Oracle 11g R2
http://docs.oracle.com/cd/E11882_01/server.112/e25554/qradv.htm
Make sure the warehouse supports the creation of the materialized view -
http://docs.oracle.com/cd/E11882_01/server.112/e25554/basicmv.htm
http://docs.oracle.com/cd/E11882_01/server.112/e25554/advmv.htm
Showing posts with label PLSQL. Show all posts
Showing posts with label PLSQL. Show all posts
Tuesday, 18 June 2013
Tuesday, 21 May 2013
Finding Day, Month, Year from a date in Oracle SQL using EXTRACT
In Oracle, to get the year, month, day or time from a date its not necessary to parse the date string using the SUBSTR function. Simply use the EXTRACT function and pass in the relevant keyword to get the value as in the following example:
SELECT EXTRACT (year FROM sysdate) "Year" FROM DUAL;
Other keywords that can be passed in are YEAR, MONTH, DAY, HOUR., MINUTE, SECOND. There are also timezone keywords that can be used with timestamps.
The function is useful when used with GROUP BY. For Example:
GROUP BY EXTRACT(month FROM start_date)
SELECT EXTRACT (year FROM sysdate) "Year" FROM DUAL;
Other keywords that can be passed in are YEAR, MONTH, DAY, HOUR., MINUTE, SECOND. There are also timezone keywords that can be used with timestamps.
The function is useful when used with GROUP BY. For Example:
GROUP BY EXTRACT(month FROM start_date)
Tuesday, 14 May 2013
Setting the value of a sequence in pl/sql in Oracle
In Oracle there is no direct way to set the value of a sequence once the sequence has been created. To set the sequence value to a specific value it is necessary to either drop and recreate the sequence, not forgetting all of the options specified in the create statement, or to increment the sequence by some positive or negative value to set the current value to the desired value.
To find out the current value of a sequence you can use the currval function on the sequence, but this will only return successfully if the sequence has already been initialized with a call to nextval. Another way to find the value for the sequence is to query the database as follows:
select sequence_name, last_number from user_sequences;
Below is sample pl/sql to set a sequence to the desired value, it defines two variables to store the current sequence and the desired sequence then alters the increment to the difference of those, increments the sequence then resets the sequence increment to the previous value. -
procedure set_seq is
l_max_row NUMBER(38,0) := 0;
l_cur_seq NUMBER(38,0) := 0;
begin
--- Now change the sequence
select max(id_col) into l_max_row from my_tab;
select my_seq.nextval into l_cur_seq from dual;
execute immediate 'alter sequence my_seq increment by ' || (l_max_row-l_cur_seq) || ' nocache';
select my_seq.nextval into l_cur_seq from dual;
execute immediate 'alter sequence my_seq increment by 1 nocache';
select my_seq.nextval into l_cur_seq from dual;
To find out the current value of a sequence you can use the currval function on the sequence, but this will only return successfully if the sequence has already been initialized with a call to nextval. Another way to find the value for the sequence is to query the database as follows:
select sequence_name, last_number from user_sequences;
Below is sample pl/sql to set a sequence to the desired value, it defines two variables to store the current sequence and the desired sequence then alters the increment to the difference of those, increments the sequence then resets the sequence increment to the previous value. -
procedure set_seq is
l_max_row NUMBER(38,0) := 0;
l_cur_seq NUMBER(38,0) := 0;
begin
--- Now change the sequence
select max(id_col) into l_max_row from my_tab;
select my_seq.nextval into l_cur_seq from dual;
execute immediate 'alter sequence my_seq increment by ' || (l_max_row-l_cur_seq) || ' nocache';
select my_seq.nextval into l_cur_seq from dual;
execute immediate 'alter sequence my_seq increment by 1 nocache';
select my_seq.nextval into l_cur_seq from dual;
Wednesday, 27 March 2013
Oracle PL/SQL Merge with sequence
In Oracle 11g it is not possible to use a sequence in the USING clause of a MERGE statement. To get around this limitation enter a dummy integer in the USING clause and specify the sequence in the VALUES clause.
Putting Sequence in the subquery following USING in a MERGE statement gives an error
-- Eg>
MERGE INTO mytab tab
USING (SELECT 1 as col1, myseq.nextval seq from dual) q1
ON (tab.col1 = q1.col1) -- The ON clause will take ANDs eg. ON (t1.c1 = t2.c1 AND t1.c2=t2.c2)
WHEN NOT MATCHED THEN
INSERT (
col1
)
VALUES (
myseq.nextval
);
Gives
Error report:
SQL Error: ORA-02287: sequence number not allowed here
02287. 00000 - "sequence number not allowed here"
*Cause: The specified sequence number (CURRVAL or NEXTVAL) is inappropriate
here in the statement.
*Action: Remove the sequence number.
Use a dummy value eg -999 instead
MERGE INTO mytab tab
USING (SELECT 1 as col1, -999 seq from dual) q1
ON (tab.col1 = q1.col1)
WHEN NOT MATCHED THEN
INSERT (
col1
)
VALUES (
myseq.nextval
);
Putting Sequence in the subquery following USING in a MERGE statement gives an error
-- Eg>
MERGE INTO mytab tab
USING (SELECT 1 as col1, myseq.nextval seq from dual) q1
ON (tab.col1 = q1.col1) -- The ON clause will take ANDs eg. ON (t1.c1 = t2.c1 AND t1.c2=t2.c2)
WHEN NOT MATCHED THEN
INSERT (
col1
)
VALUES (
myseq.nextval
);
Gives
Error report:
SQL Error: ORA-02287: sequence number not allowed here
02287. 00000 - "sequence number not allowed here"
*Cause: The specified sequence number (CURRVAL or NEXTVAL) is inappropriate
here in the statement.
*Action: Remove the sequence number.
Use a dummy value eg -999 instead
MERGE INTO mytab tab
USING (SELECT 1 as col1, -999 seq from dual) q1
ON (tab.col1 = q1.col1)
WHEN NOT MATCHED THEN
INSERT (
col1
)
VALUES (
myseq.nextval
);
Monday, 25 March 2013
Oracle 11G Shrinking Temp Tablespace
There are a few methods to shrink the temporary tablespace in Oracle 11G. In some cases you can directly resize or shrink the tablespace. If that is not possible then create a new temporary tablespace, reassign the default temp space and drop the old tablespace.
SELECT tablespace_name, file_name, bytes
FROM dba_temp_files WHERE tablespace_name like 'TEMP%';
alter database tempfile '/the/full/path/to/temp01.dbf' resize 256M;
alter database tempfile '/the/full/path/to/temp01.dbf' resize 256M
-- Can give -
ERROR at line 1:
ORA-03297: file contains used data beyond requested RESIZE value
-- If that fails, on 11G do -
alter tablespace TEMP shrink space keep 256M;
-- If that fails do
CREATE TEMPORARY TABLESPACE temp2
TEMPFILE '/datapath/temp2_01.dbf' SIZE 5M REUSE
AUTOEXTEND ON NEXT 1M MAXSIZE unlimited
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp2;
DROP TABLESPACE temp INCLUDING CONTENTS AND DATAFILES;
CREATE TEMPORARY TABLESPACE temp
2 TEMPFILE '/datapath/temp01.dbf' SIZE 256M REUSE
3 AUTOEXTEND ON NEXT 128M MAXSIZE unlimited
4 EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp;
DROP TABLESPACE temp2 INCLUDING CONTENTS AND DATAFILES;
From http://stackoverflow.com/questions/1824572/how-to-shrink-temp-tablespace-in-oracle
SELECT tablespace_name, file_name, bytes
FROM dba_temp_files WHERE tablespace_name like 'TEMP%';
alter database tempfile '/the/full/path/to/temp01.dbf' resize 256M;
alter database tempfile '/the/full/path/to/temp01.dbf' resize 256M
-- Can give -
ERROR at line 1:
ORA-03297: file contains used data beyond requested RESIZE value
-- If that fails, on 11G do -
alter tablespace TEMP shrink space keep 256M;
-- If that fails do
CREATE TEMPORARY TABLESPACE temp2
TEMPFILE '/datapath/temp2_01.dbf' SIZE 5M REUSE
AUTOEXTEND ON NEXT 1M MAXSIZE unlimited
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp2;
DROP TABLESPACE temp INCLUDING CONTENTS AND DATAFILES;
CREATE TEMPORARY TABLESPACE temp
2 TEMPFILE '/datapath/temp01.dbf' SIZE 256M REUSE
3 AUTOEXTEND ON NEXT 128M MAXSIZE unlimited
4 EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp;
DROP TABLESPACE temp2 INCLUDING CONTENTS AND DATAFILES;
From http://stackoverflow.com/questions/1824572/how-to-shrink-temp-tablespace-in-oracle
Friday, 22 March 2013
Disable Password expiry for Oracle Accounts
To disable password expiry for Oracle accounts find whihc profile is in use and then change the default timeout on the profile. If the users are already expired and locked the password must be reset and the account unlocked.
select * from dba_users; -- find the users and which profile they use
-- change the DEFAULT profile to not expire
ALTER PROFILE DEFAULT LIMIT
PASSWORD_LIFE_TIME UNLIMITED;
-- could also add FAILED_LOGIN_ATTEMPTS UNLIMITED
select * from dba_users; -- find the users and which profile they use
-- change the DEFAULT profile to not expire
ALTER PROFILE DEFAULT LIMIT
PASSWORD_LIFE_TIME UNLIMITED;
-- could also add FAILED_LOGIN_ATTEMPTS UNLIMITED
Wednesday, 20 March 2013
Oracle PL/SQL Associative Arrays using %ROWTYPE
Creating an Associative Array in Oracle PL/SQL from a table using %ROWTYPE
This example creates an in memory table using the row type from another table then populates the tbale in batches of 1000. This allows operations to be done on the data before inserting it into a third table.
procedure my_proc
is
TYPE tt_table IS TABLE OF mytable%ROWTYPE;
l_id NUMBER(38,0) := -1;
l_tab tt_table;
cursor c_data is
select * from mytable;
begin
open c_data;
loop
fetch c_data
bulk collect into l_tab limit 1000;
for i in 1 .. l_tab.count
loop
insert into other_tab (COL1)
VALUES (l_tab(i).MYCOL1);
-- Do other conditional processing here (otherwise we could just insert directly from a query)
end loop;
exit when l_tab.count = 0;
end loop;
close c_data;
end;
Also see the example of using Associative Arrays at - http://notastrophe.blogspot.com/2013/03/oracle-plsql-associative-arrays.html
This example creates an in memory table using the row type from another table then populates the tbale in batches of 1000. This allows operations to be done on the data before inserting it into a third table.
procedure my_proc
is
TYPE tt_table IS TABLE OF mytable%ROWTYPE;
l_id NUMBER(38,0) := -1;
l_tab tt_table;
cursor c_data is
select * from mytable;
begin
open c_data;
loop
fetch c_data
bulk collect into l_tab limit 1000;
for i in 1 .. l_tab.count
loop
insert into other_tab (COL1)
VALUES (l_tab(i).MYCOL1);
-- Do other conditional processing here (otherwise we could just insert directly from a query)
end loop;
exit when l_tab.count = 0;
end loop;
close c_data;
end;
Also see the example of using Associative Arrays at - http://notastrophe.blogspot.com/2013/03/oracle-plsql-associative-arrays.html
Tuesday, 19 March 2013
Oracle PL/SQL Convert BOOLEAN to STRING
In Oracle pl/sql there is no direct method to convert a boolean type to a character type. It is necessary to test the boolean with a case statement as below:
l_varchar := case l_bool when TRUE then 'TRUE' else 'FALSE' end;
l_varchar := case l_bool when TRUE then 'TRUE' else 'FALSE' end;
ORACLE PL/SQL Associative Arrays
An example of an Associative Array in Oracle 11g.
Associative arrays give you the ability to create in memory tables of a given datatype and iterate over them. This example shows the declaration of a table of character data which is populated from a select statement on an Oracle table.
-- Assign values to an empty associative array
procedure myproc
is
TYPE tt_vals IS TABLE OF VARCHAR2(80);
l_vals tt_vals;
l_count NUMBER := 1;
begin
l_vals := tt_vals(10); -- l_vals.COUNT is 1 here and l_vals.EXISTS(1) is TRUE
for mychar in (
select CHAR_COL from mytab;
)
LOOP
l_vals.extend;
l_vals(l_count) := mychar;
l_count := l_count+1;
END LOOP;
----
l_vals(1) gives the value of the first element in the array, l_vals(2) the second....
l_vals.exists(N) evaluates to TRUE if the Nth value exists, FALSE otherwise
l_vals.count gives count of elements in the array
Other Collection Methods for the Associative Array are -
LIMIT,
FIRST and LAST,
PRIOR and NEXT for looping,
TRIM,
DELETE.
See Oracle PL/SQL Language Reference (pdf)
Also - http://notastrophe.blogspot.com/2013/03/oracle-plsql-associative-arrays-using.html
Associative arrays give you the ability to create in memory tables of a given datatype and iterate over them. This example shows the declaration of a table of character data which is populated from a select statement on an Oracle table.
-- Assign values to an empty associative array
procedure myproc
is
TYPE tt_vals IS TABLE OF VARCHAR2(80);
l_vals tt_vals;
l_count NUMBER := 1;
begin
l_vals := tt_vals(10); -- l_vals.COUNT is 1 here and l_vals.EXISTS(1) is TRUE
for mychar in (
select CHAR_COL from mytab;
)
LOOP
l_vals.extend;
l_vals(l_count) := mychar;
l_count := l_count+1;
END LOOP;
----
l_vals(1) gives the value of the first element in the array, l_vals(2) the second....
l_vals.exists(N) evaluates to TRUE if the Nth value exists, FALSE otherwise
l_vals.count gives count of elements in the array
Other Collection Methods for the Associative Array are -
LIMIT,
FIRST and LAST,
PRIOR and NEXT for looping,
TRIM,
DELETE.
See Oracle PL/SQL Language Reference (pdf)
Also - http://notastrophe.blogspot.com/2013/03/oracle-plsql-associative-arrays-using.html
Wednesday, 6 February 2013
Oracle 11gR2 Disabling Fast Recovery Area (FRA)
Disabling the Fast Recovery Area
If Flashback Database is enabled, then disable it before you disable the fast recovery area.
ALTER DATABASE FLASHBACK OFF;
If you are using fast recovery area for archive logs, then set the initialization parameter LOG_ARCHIVE_DEST_n to use a non-fast recovery area location.
eg.
LOG_ARCHIVE_DEST_1='LOCATION=USE_DB_RECOVERY_FILE_DEST'
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1='LOCATION=/ORACLE/DBS/';
Disable the fast recovery area initialization parameter.
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST='';
(From Oracle Database Backup and Recovery User's Guide)
Tuesday, 15 January 2013
Shrinking UNDO Tablespace in Oracle 11gR2
To shrink UNDO tablespace in Oracle first create the new undo tablespace, then alter the database to use the new undo tablespace. This will require enough available disk space to create the new tablspace. Then drop the old tablespace to free up the disk. Commands are provided below
CREATE UNDO TABLESPACE undotbs2
DATAFILE '/u02/datafile/undotbs02.dbf'
SIZE 50M AUTOEXTEND ON NEXT 50M;
Tablespace created.
ALTER SYSTEM SET UNDO_TABLESPACE=UNDOTBS2 SCOPE=BOTH;
System altered.
DROP TABLESPACE undotbs1 INCLUDING CONTENTS AND DATAFILES;
Thursday, 1 November 2012
Oracle Find all External Table Paths
Use this query to find out the location on disk of all external tables in Oracle:
select a.owner||’.'||a.table_name||’ stored in directory ‘||b.directory_path “EXTERNAL_TABLES”
from dba_external_locations a, dba_directories b
where a.directory_owner=b.owner
and a.directory_name=b.directory_name;
Oracle Gather Table Stats
After a large load, update or delete of data in an Oracle database schema the query optimizer statistics can lead to sub-optimal performance. To gather statistics and improve performance run the following command:
begin
dbms_stats.gather_schema_stats(
ownname => 'SCHEMA',
estimate_percent => dbms_stats.auto_sample_size,
method_opt => 'for all columns size repeat',
degree => 8
);
end;
How many times have I seen this make a huge performance difference after a massive data load!
Make sure this is set as a regular job to keep the statistics up to date
Oracle Set Session Date
To alter the date format of the current connection's session information on an Oracle database run the following command:
alter session set nls_date_format = 'MM/DD/YYYY HH24:MI:SS';
alter session set nls_date_format = 'MM/DD/YYYY HH24:MI:SS';
Monday, 22 October 2012
Restart Oracle Database when FRA is full
The flash recovery area on Oracle is set to a fixed maximum size and it is possible for it to become full. When this happens Oracle will stop accepting inserts, updates, queries etc and will stop accepting connections except for SYSDBA. It will also fail to start if it is shutdown. To restart the server follow the steps below, they involve running commands as SYSDBA and editing the init.ora file.
If Oracle fails to start and startup.log shows eg:
Remove all unwanted files from the file system
To set the recovery window - in RMAN
CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 1 DAYS;
To manage flash recovery area size -
alter system set db_recovery_file_dest_size=xG SCOPE=BOTH;
To Move the FRA create a directory (preferably on a different disk) and
vi <ORACLE_HOME>/dbs/init.ora
update the line:
db_recovery_file_dest='/u02/flash_recovery_area'
(You can also change db_recovery_file_dest in here. Back up the init.ora first)
If Oracle fails to start and startup.log shows eg:
ORA-03113: end-of-file on communication channel
Process ID: 9174
Session ID: 191 Serial number: 3
Process ID: 9174
Session ID: 191 Serial number: 3
Look in alert_SID.log.
If it shows:
Errors in file /u01/app/oracle/diag/rdbms/t1234/T1234trace/T1234D_ora_10245.trc:
ORA-19809: limit exceeded for recovery files
ORA-19804: cannot reclaim 46773248 bytes disk space from 8388608000 limit
ARCH: Error 19809 Creating archive log file to '/u01/app/oracle/flash_recovery_area/T1234/archivelog/2012_11_13/o1_mf_1_20_%u_.arc'
ORA-19809: limit exceeded for recovery files
ORA-19804: cannot reclaim 46773248 bytes disk space from 8388608000 limit
ARCH: Error 19809 Creating archive log file to '/u01/app/oracle/flash_recovery_area/T1234/archivelog/2012_11_13/o1_mf_1_20_%u_.arc'
Then the flash recovery area is full.
To fix on a test instance (ie not production data) run
sqlplus / as SYSDBA
startup mount
alter database noarchivelog;
Remove all unwanted files from the file system
Then go into rman
rman TARGET sys/pwd@SID
crosscheck archivelog all;
delete expired archivelog all;
delete force obsolete;
delete force obsolete;
Then sqlplus / as SYSDBA
alter database archivelog;
alter database open;
To set the recovery window - in RMAN
CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 1 DAYS;
To manage flash recovery area size -
alter system set db_recovery_file_dest_size=xG SCOPE=BOTH;
To Move the FRA create a directory (preferably on a different disk) and
vi <ORACLE_HOME>/dbs/init.ora
update the line:
db_recovery_file_dest='/u02/flash_recovery_area'
(You can also change db_recovery_file_dest in here. Back up the init.ora first)
Thursday, 18 October 2012
Shrink Oracle DBF Files
SQL commands for finding block size and size of all tablespace files in an Oracle database. THe script produces the necessary commands to reduce the disk space used in the related dbf files.
select value from v$parameter where name = 'db_block_size'
COLUMN SHRINK_DATAFILES FORMAT A75 WORD_WRAPPED
COLUMN VALUE NEW_VAL BLKSIZE
SELECT VALUE FROM V$PARAMETER WHERE NAME = 'db_block_size';
SELECT 'ALTER DATABASE DATAFILE ''' || FILE_NAME || ''' RESIZE ' || CEIL( (NVL(HWM,1)*&&BLKSIZE)/1024/1024 ) ||
'M;' SHRINK_DATAFILES FROM DBA_DATA_FILES DBADF,
(SELECT FILE_ID, MAX(BLOCK_ID+BLOCKS-1) HWM FROM DBA_EXTENTS GROUP BY FILE_ID ) DBAFS
WHERE DBADF.FILE_ID = DBAFS.FILE_ID(+) AND CEIL(BLOCKS*&&BLKSIZE/1024/1024)- CEIL((NVL(HWM,1)* &&BLKSIZE)/1024/1024 ) > 0;
SHRINK_DATAFILES
---------------------------------------------------------------------------
ALTER DATABASE DATAFILE 'F:\ORACLE\ORADATA\MYDBF\RBS01.DBF' RESIZE 25M;
select value from v$parameter where name = 'db_block_size'
COLUMN SHRINK_DATAFILES FORMAT A75 WORD_WRAPPED
COLUMN VALUE NEW_VAL BLKSIZE
SELECT VALUE FROM V$PARAMETER WHERE NAME = 'db_block_size';
SELECT 'ALTER DATABASE DATAFILE ''' || FILE_NAME || ''' RESIZE ' || CEIL( (NVL(HWM,1)*&&BLKSIZE)/1024/1024 ) ||
'M;' SHRINK_DATAFILES FROM DBA_DATA_FILES DBADF,
(SELECT FILE_ID, MAX(BLOCK_ID+BLOCKS-1) HWM FROM DBA_EXTENTS GROUP BY FILE_ID ) DBAFS
WHERE DBADF.FILE_ID = DBAFS.FILE_ID(+) AND CEIL(BLOCKS*&&BLKSIZE/1024/1024)- CEIL((NVL(HWM,1)* &&BLKSIZE)/1024/1024 ) > 0;
SHRINK_DATAFILES
---------------------------------------------------------------------------
ALTER DATABASE DATAFILE 'F:\ORACLE\ORADATA\MYDBF\RBS01.DBF' RESIZE 25M;
Unlock Locked SYSDBA
Commands for unlocking a locked SYSDBA account in Oracle.
SET ORACLE_SID=orcl
sqlplus / AS SYSDBA
ALTER USER SYSTEM ACCOUNT UNLOCK
or ALTER USER SYSTEM IDENTIFIED BY <NEW PASSWORD> ACCOUNT UNLOCK
SET ORACLE_SID=orcl
sqlplus / AS SYSDBA
ALTER USER SYSTEM ACCOUNT UNLOCK
or ALTER USER SYSTEM IDENTIFIED BY <NEW PASSWORD> ACCOUNT UNLOCK
Subscribe to:
Posts (Atom)