Showing posts with label SQL. Show all posts
Showing posts with label SQL. Show all posts

9/09/2017

Oracle how to move and rename datafiles

First of all, you don't have to restart the database. Renaming data files is very common due to the following reasons. 

Maybe you don't like the name of data file and want to keep a naming method, or the most important, you want to move the datafile to a new, faster filesystem with more empty space. Moving datafiles is something that you need when you will start searching how I/O is spread on you filesystems! 

How to 
For our example. Let's say that the name of the tablespace is TBS1 and the datafile is '/filesystem01/tbs01.dbf' and you want to move it to '/filesystem02/tbs01.dbf' 

1. First take the tablespace offline

ALTER TABLESPACE TBS1 OFFLINE;

If someone is using the tablespace, then you can't take it offline! You must kill all sessions using it. The time needed to take it offline, depends on the size of tablespace, a 10Mbytes tablespace may take 1 sec, a 1TByte tablespace may take some minutes… so be patient. 

2. Move the datafile to the new filesystem with the os command.

$>mv /filesystem01/tbs01.dbf /filesystem02/tbs01.dbf

3. Do the renaming to update the dictionary and controlfile

ALTER TABLESPACE TBS1 RENAME DATAFILE '/filesystem01/tbs01.dbf' 
TO '/filesystem02/tbs01.dbf';
4. Take back tablespace online.

ALTER TABLESPACE TBS1 ONLINE;

Oracle How to find user object grants

Here  with this query you can find the objects grants for a specific user.

SELECT tpm.NAME PRIVILEGE,

       DECODE (MOD (oa.OPTION$, 2), 1, 'YES', 'NO') grantable,
       ue.NAME Grantee, ur.NAME grantor, u.NAME owner,
       DECODE (o.TYPE#,
               0, 'NEXT OBJECT',
               1, 'INDEX',
               2, 'TABLE',
               3, 'CLUSTER',
               4, 'VIEW',
               5, 'SYNONYM',
               6, 'SEQUENCE',
               7, 'PROCEDURE',
               8, 'FUNCTION',
               9, 'PACKAGE',
               11, 'PACKAGE BODY',
               12, 'TRIGGER',
               13, 'TYPE',
               14, 'TYPE BODY',
               19, 'TABLE PARTITION',
               20, 'INDEX PARTITION',
               21, 'LOB',
               22, 'LIBRARY',
               23, 'DIRECTORY',
               24, 'QUEUE',
               28, 'JAVA SOURCE',
               29, 'JAVA CLASS',
               30, 'JAVA RESOURCE',
               32, 'INDEXTYPE',
               33, 'OPERATOR',
               34, 'TABLE SUBPARTITION',
               35, 'INDEX SUBPARTITION',
               40, 'LOB PARTITION',
               41, 'LOB SUBPARTITION',
               42, 'MATERIALIZED VIEW',
               43, 'DIMENSION',
               44, 'CONTEXT',
               46, 'RULE SET',
               47, 'RESOURCE PLAN',
               48, 'CONSUMER GROUP',
               51, 'SUBSCRIPTION',
               52, 'LOCATION',
               55, 'XML SCHEMA',
               56, 'JAVA DATA',
               57, 'SECURITY PROFILE',
               59, 'RULE',
               62, 'EVALUATION CONTEXT',
               'UNDEFINED'
              ) object_type,
       o.NAME object_name, '' column_name
  FROM SYS.objauth$ oa, SYS.obj$ o, SYS.USER$ u, SYS.USER$ ur, SYS.USER$ ue,
 table_privilege_map tpm
 WHERE oa.obj# = o.obj#
   AND oa.grantor# = ur.USER#
   AND oa.Grantee# = ue.USER#
   AND oa.col# IS NULL
   AND oa.PRIVILEGE# = tpm.PRIVILEGE
   AND u.USER# = o.owner#
   AND o.TYPE# IN (2, 4, 6, 9, 7, 8, 42, 23, 22, 13, 33, 32)
   AND ue.NAME = 'NISA_DL'
UNION ALL                                               -- column level grants
SELECT tpm.NAME PRIVILEGE,
       DECODE (MOD (oa.OPTION$, 2), 1, 'YES', 'NO') grantable,
       ue.NAME Grantee, ur.NAME grantor, u.NAME owner,
       DECODE (o.TYPE#,
               0, 'NEXT OBJECT',
               1, 'INDEX',
               2, 'TABLE',
               3, 'CLUSTER',
               4, 'VIEW',
               5, 'SYNONYM',
               6, 'SEQUENCE',
               7, 'PROCEDURE',
               8, 'FUNCTION',
               9, 'PACKAGE',
               11, 'PACKAGE BODY',
               12, 'TRIGGER',
               13, 'TYPE',
               14, 'TYPE BODY',
               19, 'TABLE PARTITION',
               20, 'INDEX PARTITION',
               21, 'LOB',
               22, 'LIBRARY',
               23, 'DIRECTORY',
               24, 'QUEUE',
               28, 'JAVA SOURCE',
               29, 'JAVA CLASS',
               30, 'JAVA RESOURCE',
               32, 'INDEXTYPE',
               33, 'OPERATOR',
               34, 'TABLE SUBPARTITION',
               35, 'INDEX SUBPARTITION',
               40, 'LOB PARTITION',
               41, 'LOB SUBPARTITION',
               42, 'MATERIALIZED VIEW',
               43, 'DIMENSION',
               44, 'CONTEXT',
               46, 'RULE SET',
               47, 'RESOURCE PLAN',
               48, 'CONSUMER GROUP',
               51, 'SUBSCRIPTION',
               52, 'LOCATION',
               55, 'XML SCHEMA',
               56, 'JAVA DATA',
               57, 'SECURITY PROFILE',
               59, 'RULE',
               62, 'EVALUATION CONTEXT',
               'UNDEFINED'
              ) object_type,
       o.NAME object_name, c.NAME column_name
  FROM SYS.objauth$ oa, SYS.obj$ o, SYS.USER$ u, SYS.USER$ ur, SYS.USER$ ue, SYS.col$ c,
 table_privilege_map
 tpm
 WHERE oa.obj# = o.obj#
   AND oa.grantor# = ur.USER#
   AND oa.Grantee# = ue.USER#
   AND oa.obj# = c.obj#
   AND oa.col# = c.col#
   AND BITAND (c.property, 32) = 0                     /* not hidden column */
   AND oa.col# IS NOT NULL
   AND oa.PRIVILEGE# = tpm.PRIVILEGE
   AND u.USER# = o.owner#
   AND o.TYPE# IN (2, 4)
   AND ue.NAME = 'NISA_DL';

check rman backup completion time oracle

You can find your database backup time with the following query



SELECT * FROM (SELECT END.dt, 'Incremental' BACKUP, STAR.TIME started, END.TIME END,  
DECODE(TRUNC(END.TIME - star.TIME), 0, NULL, TRUNC(END.TIME - star.TIME) || ' Days' || ' + ') ||
TO_CHAR(TO_DATE(TRUNC(MOD(END.TIME - star.TIME,1) * 86400), 'SSSSS'), 'HH24:MI:SS') TIME
FROM 
(SELECT TRUNC(start_time) dt , MAX(COMPLETION_TIME) TIME FROM V$BACKUP_SET WHERE BACKUP_TYPE='I'
GROUP BY TRUNC(start_time)) END, 
(SELECT TRUNC(start_time) dt, MIN(START_TIME) TIME FROM V$BACKUP_SET WHERE BACKUP_TYPE='I'
GROUP BY TRUNC(start_time)) STAR
WHERE END.dt = STAR.dt 
UNION ALL
SELECT END.dt, 'Full Database' BACKUP, STAR.TIME started, END.TIME END,  
DECODE(TRUNC(END.TIME - star.TIME), 0, NULL, TRUNC(END.TIME - star.TIME) || ' Days' || ' + ') ||
TO_CHAR(TO_DATE(TRUNC(MOD(END.TIME - star.TIME,1) * 86400), 'SSSSS'), 'HH24:MI:SS') TIME
FROM 
(SELECT TRUNC(start_time) dt , MAX(COMPLETION_TIME) TIME FROM V$BACKUP_SET WHERE BACKUP_TYPE='D'
GROUP BY TRUNC(start_time)) END, 
(SELECT TRUNC(start_time) dt, MIN(START_TIME) TIME FROM V$BACKUP_SET WHERE BACKUP_TYPE='D'
GROUP BY TRUNC(start_time)) STAR
WHERE END.dt = STAR.dt) 
ORDER BY dt ASC;

DT         BACKUP        STARTED    END        TIME
---------- ------------- ---------- ---------- --------
13/10/2010 Incremental   13/10/2010 13/10/2010 01:16:39
14/10/2010 Incremental   14/10/2010 14/10/2010 02:03:00
16/10/2010 Full Database 16/10/2010 16/10/2010 05:40:09
18/10/2010 Incremental   18/10/2010 18/10/2010 01:55:08
19/10/2010 Incremental   19/10/2010 19/10/2010 01:55:57
20/10/2010 Incremental   20/10/2010 20/10/2010 02:29:29
21/10/2010 Incremental   21/10/2010 21/10/2010 02:10:50
23/10/2010 Full Database 23/10/2010 23/10/2010 06:08:06
25/10/2010 Incremental   25/10/2010 25/10/2010 02:27:07
26/10/2010 Incremental   26/10/2010 26/10/2010 01:34:12
27/10/2010 Incremental   27/10/2010 27/10/2010 01:50:09
28/10/2010 Incremental   28/10/2010 28/10/2010 01:35:10
30/10/2010 Full Database 30/10/2010 30/10/2010 05:24:12
01/11/2010 Incremental   01/11/2010 01/11/2010 02:03:43
02/11/2010 Incremental   02/11/2010 02/11/2010 00:47:35

Oracle How to calculate export dump size

Sometimes you have to export all the database or many schemas but you don't have all the necessary space needed, or you don't know exactly how much space the dmp file it will take. 

Oracle with exports (or expdp) stores at the dmp file the table data. Indexes are just "Create index statements" which will be created after loading the table data. So the key factor of how big will be your dmp file, depends on how much table data you have. 

The following query calculates how much table data each schema takes on your database



SELECT owner, ROUND(SUM(size_mb)) MBytes FROM 
(
SELECT owner, segment_name, segment_type, partition_name,
ROUND(bytes/(1024*1024),2) SIZE_MB,
tablespace_name 
FROM DBA_SEGMENTS 
WHERE SEGMENT_TYPE IN ('TABLE', 'TABLE PARTITION',
 'TABLE SUBPARTITION') 
--AND TABLESPACE_NAME LIKE 'COSTE%' 
--AND SEGMENT_NAME LIKE 'OE_ORDER_LINES_ALL%' 
--AND partition_name LIKE 'USAGE_FCT_NEW%'
--AND OWNER = 'TARGET_DW' 
--AND ROUND(bytes/(1024*1024),2) > 1000)
) 
GROUP BY owner 
ORDER BY MBytes DESC;

OWNER                              MBYTES
------------------------------ ----------
TARGET_DW                         3774208
TARGET_POC                         673192
STAGE_DW                           469263
PRESTAGE_DW                        389326
SHADOW_DW                          257233
PRESENT_PERIF                      148063
SNAP                               141565
PKIOUSIS                           117535
DM_SPSS                             44760
MONITOR_DW                          35336
CUSTOMER_VIEW                       29807

for example if you export the SHADOW_DW schema, it will create a dmp file approximately 257233MB->250GBytes. 

Tip: 
Bear in mind that the actual dump file will have smaller size than 250GB!!!, because in most cases the TABLE DATA are fragmented!. Export-Datapump, removes fragmentation!. 

Indexes, packages, procedures, views, etc, are not taking too much space in the dmp file, are just DDL statements.



SELECT 'expdp SYSTEM/oracle DUMPFILE=' || owner || '_%U.dmp
 DIRECTORY=exp_dir PARALLEL=10 LOGFILE='
 || owner ||'.log schemas= ' || owner SQL
FROM (
SELECT owner, ROUND(SUM(size_mb)) MBytes FROM 
(
SELECT owner, segment_name, segment_type, partition_name,
 ROUND(bytes/(1024*1024),2) SIZE_MB,
 tablespace_name 
FROM DBA_SEGMENTS 
WHERE SEGMENT_TYPE IN ('TABLE', 'TABLE PARTITION',
 'TABLE SUBPARTITION') 
--AND TABLESPACE_NAME LIKE 'COSTE%' 
--AND SEGMENT_NAME LIKE 'OE_ORDER_LINES_ALL%' 
--AND partition_name LIKE 'USAGE_FCT_NEW%'
AND OWNER <> 'SYSTEM' 
--AND ROUND(bytes/(1024*1024),2) > 1000)
) 
GROUP BY owner 
ORDER BY MBytes DESC);

How to create oracle database with sqlplus


In case you want to create an Oracle Database, without the GUI (dbca), use the following simple steps: 

1. First set the enviroment for the oracle user.


export ORACLE_HOME=/oradb/CUSTDB/orabin/11.2.0
export PATH=/oradb/CUSTDB/orabin/11.2.0/bin:$PATH
export ORACLE_SID=CUSTDB
export TNS_ADMIN=/oradb/CUSTDB/orabin/11.2.0/network/admin

2. Create the initSID.ora (for example SID=CUSTDB) 

The file usually is located in the $ORACLE_HOME/dbs/initSID.ora

db_name='CUSTDB'
memory_target=1G
processes = 500
audit_file_dest='/oradb/CUSTDB/orabin/11.2.0/rdbms/audit'
audit_trail ='db'
db_block_size=8192
db_domain=''
db_recovery_file_dest='/oradb/CUSTDB/oraarch'
db_recovery_file_dest_size=4G
diagnostic_dest='/oradb/CUSTDB/orabin/oradiag_oracust'
open_cursors=300 
remote_login_passwordfile='EXCLUSIVE'
undo_tablespace='UNDOTBS'
control_files = (/oradb/CUSTDB/oradata1/controlfiles/control1.ctl,
/oradb/CUSTDB/oradata2/controlfiles/control2.ctl,
/oradb/CUSTDB/oradata2/controlfiles/control2.ctl)
compatible ='11.2.0'

3. Login as oracle user and startup nomount the database 

sqlplus "/ as sysdba" 
SQL>startup nomount pfile=$ORACLE_HOME/dbs/initSID.ora 

4. Run the script to create the database


CREATE DATABASE CUSTDB
   USER SYS IDENTIFIED BY password
   USER SYSTEM IDENTIFIED BY password
   LOGFILE GROUP 1 ('/oradb/CUSTDB/oradata1/redologs/redo01_a.rdlog',
 '/oradb/CUSTDB/oradata2/redologs/redo01_b.rdlog') SIZE 1024M,
           GROUP 2 ('/oradb/CUSTDB/oradata2/redologs/redo02_a.rdlog',
 '/oradb/CUSTDB/oradata3/redologs/redo02_b.rdlog') SIZE 1024M,
           GROUP 3 ('/oradb/CUSTDB/oradata3/redologs/redo03_a.rdlog',
 '/oradb/CUSTDB/oradata1/redologs/redo03_b.rdlog') SIZE 1024M,
           GROUP 4 ('/oradb/CUSTDB/oradata1/redologs/redo04_a.rdlog',
 '/oradb/CUSTDB/oradata2/redologs/redo04_b.rdlog') SIZE 1024M
   MAXLOGFILES 5
   MAXLOGMEMBERS 5
   MAXLOGHISTORY 1
   MAXDATAFILES 1000
   CHARACTER SET AL32UTF8
   NATIONAL CHARACTER SET AL16UTF16
   EXTENT MANAGEMENT LOCAL
   DATAFILE '/oradb/CUSTDB/oradata1/datafiles/system01.dbf'
 SIZE 3000M REUSE
   SYSAUX DATAFILE '/oradb/CUSTDB/oradata1/datafiles/sysaux01.dbf'
 SIZE 1000M REUSE
   DEFAULT TABLESPACE users
      DATAFILE '/oradb/CUSTDB/oradata1/datafiles/users01.dbf'
      SIZE 10M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED
   DEFAULT TEMPORARY TABLESPACE temp
      TEMPFILE '/oradb/CUSTDB/oradata1/datafiles/temp01.dbf'
      SIZE 1000M REUSE
   UNDO TABLESPACE undotbs
      DATAFILE '/oradb/CUSTDB/oradata1/datafiles/undotbs01.dbf'
      SIZE 2000M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

Of course, you have to modify appropriately for your case. 

5. Run the following scripts to create dictionary and basic
 database functionality.

sqlplus "/ as sysdba"
SQL>@$ORACLE_HOME/rdbms/admin/catalog.sql
SQL>@$ORACLE_HOME/rdbms/admin/catproc.sql

login as SYSTEM user and run the script

SQL>@$ORACLE_HOME/sqlplus/admin/pupbld.sql

Oracle Table space vs index space

It is very common as time passes the database to constantly grow. You can calculate the tables and indexes space occupied with the following script.
SELECT SUBSTR(segment_type, 0, 18) SEGMENT, SUM(size_mb) size_mb, 
ROUND((RATIO_TO_REPORT(SUM(size_mb)) OVER ())*100, 2)|| '%' PERC
FROM (
SELECT segment_type, ROUND(SUM(size_mb)) size_mb 
FROM (SELECT owner, segment_name, segment_type, partition_name,
ROUND(bytes/(1024*1024),2)
SIZE_MB, tablespace_name 
FROM DBA_SEGMENTS 
WHERE SEGMENT_TYPE IN ('LOBINDEX', 'INDEX PARTITION',
'INDEX SUBPARTITION', 'INDEX', 
'TABLE SUBPARTITION', 'TABLE PARTITION', 'LOB PARTITION',
'LOBSEGMENT', 'TABLE', 'LOB SUBPARTITION') 
ORDER BY bytes DESC) 
GROUP BY segment_type 
ORDER BY size_mb DESC) 
GROUP BY SUBSTR(segment_type, 0, 18);

SEGMENT               SIZE_MB PERC
------------------ ---------- --------
TABLE SUBPARTITION    1980567 17,18%
INDEX PARTITION       1333269 11,56%
LOBINDEX                  298 0%
TABLE PARTITION       1806063 15,67%
LOB PARTITION           12080 ,1%
INDEX SUBPARTITION    2240245 19,43%
LOBSEGMENT             157713 1,37%
TABLE                 3275990 28,42%
INDEX                  722279 6,27%

9 rows selected.

If someone wants to have a better grouping like tables against indexes and lob space can use the following.

SELECT SUBSTR(segment_type, 0, 3) SEGMENT, SUM(size_mb) size_mb,
ROUND((RATIO_TO_REPORT(SUM(size_mb)) OVER ())*100, 2)|| '%' PERCFROM (SELECT segment_type, ROUND(SUM(size_mb)) size_mb
FROM (SELECT owner, segment_name, segment_type, partition_name, ROUND(bytes/(1024*1024),2) SIZE_MB, tablespace_name
FROM DBA_SEGMENTS
WHERE SEGMENT_TYPE IN ('LOBINDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION', 'INDEX',
'TABLE SUBPARTITION', 'TABLE PARTITION', 'LOB PARTITION', 'LOBSEGMENT', 'TABLE', 'LOB SUBPARTITION')
ORDER BY bytes DESC)
GROUP BY segment_type
ORDER BY size_mb DESC)
GROUP BY SUBSTR(segment_type, 0, 3); SEG SIZE_MB PERC--- ---------- ----------TAB 7062620 61,26%LOB 170091 1,48%IND 4295793 37,26%

Oracle how to Send emails from the database

A simple procedure to send emails from the database.
You just need to know the IP of the SMTP email server.


CREATE OR REPLACE PROCEDURE mail_send(sender IN VARCHAR2,
recipient IN VARCHAR2,
subject IN VARCHAR2,
message IN VARCHAR2)
IS

mail_conn utl_smtp.connection;
test varchar2(200);
crlf varchar2(2):= CHR( 13 ) || CHR( 10 );
mesg varchar2(2000);

BEGIN

mail_conn := utl_smtp.open_connection('60.212.02.34');
utl_smtp.helo(mail_conn, 'albert.einstein.com');
utl_smtp.mail(mail_conn, sender);
utl_smtp.rcpt(mail_conn, recipient);

mesg:= subject || ' ' || crlf || message || crlf;
utl_smtp.data(mail_conn, mesg);
utl_smtp.quit(mail_conn);
END;
/

For example login to sqlplus and run

BEGIN
mail_send('spiderman@dbc.com','ospiderman@dbc.com', 'tablespace error', 'You need to add more space!!!!');
END;
/

You can also setup an emailing list, a simple table with the email of the recipients.

CREATE TABLE HELPDESK.S_RECIPIENTS
(
  RECIPIENT   VARCHAR2(200)
)
TABLESPACE HELPDESK
PCTUSED    40
PCTFREE    10
INITRANS   1
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            NEXT             64K
            MINEXTENTS       1
            MAXEXTENTS       2147483645
            PCTINCREASE      0
            FREELISTS        1
            FREELIST GROUPS  1
            BUFFER_POOL      DEFAULT
           )
LOGGING 
NOCACHE
NOPARALLEL;

INSERT INTO HELPDESK.S_RECIPIENTS VALUES ('spiderman@dbc.com');
INSERT INTO HELPDESK.S_RECIPIENTS VALUES ('ospiderman@dbc.com');
COMMIT;

How to Shutdown Oracle database NORMAL quick

Shutdown Oracle database NORMAL without waiting forever

Shutdown Normal will only shutdown Oracle when there are no remaining connections to Oracle. That in big systems with thousands of connections means waiting forever. So what can you do if you must shutdown the database with the Normal option?

You can:

1. Shutdown database with ABORT or IMMEDIATE option.
2. Restart the database with RESTRICT mode.
3. Shutdown it down again with NORMAL option. 

9/08/2017

Oracle how to increase performance with DECODE function

If you have filtered with an IN (..,..) you've noticed some heavy performance hits. If you look at the explain plan, you'll find that it is producing table scans for each of the elements in the IN list. There is a logically equivalent method using a DECODE() function that reduces it to a single scan. If you have a filter that looks like:
where state_code in ('TX','OK','LA','NM');
You can replace it with:
where decode(state_code,'TX',1,'OK',1,'LA',1,'NM',1,0) = 1;

and significantly reduce your table scans.
(Note the 0 as the default in the decode results.)

Oracle how to truncate table from remote database

When you try to truncate a table on a remote database, you will get the following error: 

ORA-02021: DDL operations are not allowed on a remote database. 
You have a database link to the remote database so you can see objects there and execute them (e.g. procedures, functions, packages, triggers, etc). The solution is to create the following procedure on the remote database, then execute it from the local one.


CREATE OR REPLACE PROCEDURE Trunc_RMT_Table(p_table_name VARCHAR2) AS

   v_sql_error_code PLS_INTEGER;
   v_sql_error_message VARCHAR2(512);

BEGIN
   EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || p_table_name;
EXCEPTION
   WHEN OTHERS THEN
      v_sql_error_code := SQLCODE;
      v_sql_error_message := SQLERRM(v_sql_error_code);
      DBMS_OUTPUT.ENABLE(5000);
      DBMS_OUTPUT.PUT_LINE('OTHER ERROR');
      DBMS_OUTPUT.PUT_LINE(v_sql_error_message);
END Truncate_Remote_Table;
/
To execute the procedure, use the following from the local database:
BEGIN
   Trunc_RMT_Table@db_link(remote_table_name);
END;
/

Oracle how to remove bad child records from table

Remove bad child records to enable or create a foreign key in table


If you get "Parent Keys Not Found" error when you try to enable/create relation from a child table to the parent table, then you must identify and remove bad 'child' records. 

The records can be identified and removed using the query:
DELETE FROM childtablename ct
WHERE NOT EXISTS (SELECT 'x' FROM parenttablename pt 
WHERE ct.keycolumn1 = pt.keycolumn1 AND
ct.keycolumn2 = pt.keycolumn2...);

SQL How to remove spaces from string

So, in order to remove all left and right spaces from string run this simple script.



SELECT RTRIM(LTRIM(' shhdaaahjfhopenopendatabasehf ')) FROM DUAL;

Oracle sql delete duplicate records from table

In the case when you need to identify duplicate rows and remove them from the table - use the SQL query below.


SELECT * FROM some_table WHERE ROWID NOT IN
(SELECT MIN (ROWID) FROM table_with_duplicates 
GROUP BY col1, col2, col3);

DELETE FROM some_table WHERE ROWID NOT IN
(SELECT MIN (ROWID) FROM table_with_duplicates  
GROUP BY col1, col2, col3);

Popular Posts