Experts
Red Gate Oracle Tools
Log in
Search ATO...
All Things Oracle
Full Articles
Webinars
Experts
Database Dev
App Dev
DBA
PL/SQL
APEX
Puzzles
Oracle Database 12c New Features – Part I
Syed Jaffar Hussain on 27 June 2013 with 54 comments
During this Oracle Database 12c new features article series, I shall be extensively exploring some of the very important new additions
and enhancements introduced in the area of Database Administration, RMAN, High Availability and Performance Tuning.
Part I covers:
1. Online migration of an active data file
2. Online table partition or subpartition migration
3. Invisible column
4. Multiple indexes on the same column
5. DDL logging
6. Temporary undo in and outs
7. New backup user privilege
8. How to execute SQL statement in RMAN
9. Table level recovery in RMAN
10. Restricting PGA size
1. Online rename and relocation of an active data file
Unlike in the previous releases, a data file migration or renaming in Oracle database 12c R1 no longer requires a number of steps i.e.
putting the tablespace in READ ONLY mode, followed by data file offline action. In 12c R1, a data file can be renamed or moved online
simply using the ALTER DATABASE MOVE DATAFILE SQL statement. While the data file is being transferred, the end user can
perform queries, DML and DDL tasks. Additionally, data files can be migrated between storages e.g. from nonASM to ASM and vice
versa.
Rename a data file:
SQL> ALTER DATABASE MOVE DATAFILE '/u00/data/users01.dbf' TO '/u00/data/users_01.dbf';
Migrate a data file from nonASM to ASM:
SQL> ALTER DATABASE MOVE DATAFILE '/u00/data/users_01.dbf' TO '+DG_DATA';
Migrate a data file from one ASM disk group to another:
SQL> ALTER DATABASE MOVE DATAFILE '+DG_DATA/DBNAME/DATAFILE/users_01.dbf ' TO '+DG_DATA_02';
Overwrite the data file with the same name, if it exists at the new location:
SQL> ALTER DATABASE MOVE DATAFILE '/u00/data/users_01.dbf' TO '/u00/data_new/users_01.dbf' REUSE;
Copy the file to a new location whilst retaining the old copy in the old location:
SQL> ALTER DATABASE MOVE DATAFILE '/u00/data/users_01.dbf' TO '/u00/data_new/users_01.dbf' KEEP;
You can monitor the progress while a data file being moved by querying the v$session_longops dynamic view. Additionally, you can
also refer the alert.log of the database where Oracle writes the details about action being taken place.
2. Online migration of table partition or subpartition
Migration of a table partition or subpartition to a different tablespace no longer requires a complex procedure in Oracle 12c R1. In a
similar way to how a heap (nonpartition) table online migration was achieved in the previous releases, a table partition or subpartition
can be moved to a different tablespace online or offline. When an ONLINE clause is specified, all DML operations can be performed
without any interruption on the partition|subpartition which is involved in the procedure. In contrast, no DML operations are allowed if
the partition|subpartition is moved offline.
Here are some working examples:
SQL> ALTER TABLE table_name MOVE PARTITION|SUBPARTITION partition_name TO tablespace tablespace_name;
SQL> ALTER TABLE table_name MOVE PARTITION|SUBPARTITION partition_name TO tablespace tablespace_name UPDATE INDEXES ONLINE;
The first example is used to move a table partition|subpartition to a new tablespace offline. The second example moves a table
partition/subpartitioning online maintaining any local/global indexes on the table. Additionally, no DML operation will get interrupted
when ONLINE clause is mentioned.
Important notes:
The UPDATE INDEXES clause will avoid any local/global indexes going unusable on the table.
Table online migration restriction applies here too.
There will be locking mechanism involved to complete the procedure, also it might leads to performance degradation and can
generate huge redo, depending upon the size of the partition, subpartition.
3. Invisible columns
In Oracle 11g R1, Oracle introduced a couple of good enhancements in the form of invisible indexes and virtual columns. Taking the
legacy forward, invisible column concepts has been introduced in Oracle 12c R1. I still remember, in the previous releases, to hide
important data –columns from being displayed in the generic queries– we used to create a view hiding the required information or apply
some sort of security conditions.
In 12c R1, you can now have an invisible column in a table. When a column is defined as invisible, the column won’t appear in generic
queries, unless the column is explicitly referred to in the SQL statement or condition, or DESCRIBED in the table definition. It is pretty
easy to add or modify a column to be invisible and vice versa:
SQL> CREATE TABLE emp (eno number(6), ename name varchar2(40), sal number(9) INVISIBLE);
SQL> ALTER TABLE emp MODIFY (sal visible);
You must explicitly refer to the invisible column name with the INSERT statement to insert the database into invisible columns. A virtual
column or partition column can be defined as invisible too. However, temporary tables, external tables and cluster tables won’t support
invisible columns.
4. Multiple indexes on the same column
Pre Oracle 12c, you can’t create multiple indexes either on the same column or set of columns in any form. For example, if you have an
index on column {a} or columns {a,b}, you can’t create another index on the same column or set of columns in the same order. In 12c,
you can have multiple indexes on the same column or set of columns as long as the index type is different. However, only one type of
index is usable/visible at a given time. In order to test the invisible indexes, you need to set the
optimizer_use_use_invisible_indexes=true.
Here’s an the example:
SQL> CREATE INDEX emp_ind1 ON EMP(ENO,ENAME);
SQL> CREATE BITMAP INDEX emp_ind2 ON EMP(ENO,ENAME) INVISIBLE;
5. DDL logging
There was no direction option available to log the DDL action in the previous releases. In 12cR1, you can now log the DDL action into
xml and log files. This will be very useful to know when the drop or create command was executed and by who. The
ENABLE_DDL_LOGGING initiation parameter must be configured in order to turn on this feature. The parameter can be set at the
database or session levels. When this parameter is enabled, all DDL commands are logged in an xml and a log file under the
$ORACLE_BASE/diag/rdbms/DBNAME/log|ddl location. An xml file contains information, such as DDL command, IP address,
timestamp etc. This helps to identify when a user or table dropped or when a DDL statement is triggered.
To enable DDL logging
SQL> ALTER SYSTEM|SESSION SET ENABLE_DDL_LOGGING=TRUE;
The following DDL statements are likely to be recorded in the xml/log file:
CREATE|ALTER|DROP|TRUNCATE TABLE
DROP USER
CREATE|ALTER|DROP PACKAGE|FUNCTION|VIEW|SYNONYM|SEQUENCE
6. Temporary Undo
Each Oracle database contains a set of system related tablespaces, such as, SYSTEM, SYSAUX, UNDO & TEMP, and each are used for
different purposes within the Oracle database. Pre Oracle 12c R1, undo records generated by the temporary tables used to be stored in
undo tablespace, much similar to a general/persistent table undo records. However, with the temporary undo feature in 12c R1, the
temporary undo records can now be stored in a temporary table instead of stored in undo tablespace. The prime benefits of temporary
undo includes: reduction in undo tablespace and less redo data generation as the information won’t be logged in redo logs. You have the
flexibility to enable the temporary undo option either at session level or database level.
Enabling temporary undo
To be able to use the new feature, the following needs to be set:
Compatibility parameter must be set to 12.0.0 or higher
Enable TEMP_UNDO_ENABLED initialization parameter
Since the temporary undo records now stored in a temp tablespace, you need to create the temporary tablespace with sufficient
space
For session level, you can use: ALTER SESSION SET TEMP_UNDO_ENABLE=TRUE;
Query temporary undo information
The dictionary views listed below are used to view/query the information/statistics about the temporary undo data:
V$TEMPUNDOSTAT
DBA_HIST_UNDOSTAT
V$UNDOSTAT
To disable the feature, you simply need to set the following:
SQL> ALTER SYSTEM|SESSION SET TEMP_UNDO_ENABLED=FALSE;
7. Backup specific user privilege
In 11g R2, SYSASM privilege was introduced to perform ASM specific operations. Similarly, backup and recovery tasks specific
privilege SYSBACKUP has been introduced in 12c to execute backup and recovery commands in Recovery Manager (RMAN).
Therefore, you can create a local user in the database and grant the SYSBACKUP privilege to perform any backup and recovery related
tasks in RMAN without being granting the SYSDBA privilege.
$ ./rman target "username/password as SYSBACKUP"
8. How to execute SQL statement in RMAN
In 12c, you can now execute any SQL and PL/SQL commands in RMAN without the need of a SQL prefix: you can execute any SQL
and PLS/SQL commands directly from RMAN. How you can execute SQL statements in RMAN:
RMAN> SELECT username,machine FROM v$session;
RMAN> ALTER TABLESPACE users ADD DATAFILE SIZE 121m;
9. Table or partition recovery in RMAN
Oracle database backups are mainly categorized into two types: logical and physical. Each backup type has its own pros and cons. In
previous editions, it was not feasible to restore a table or partition using existing physical backups. In order to restore a particular object,
you must have logical backup. With 12c R1, you can recover a particular table or partition to a pointintime or SCN from RMAN
backups in the event of a table drop or truncate.
When a table or partition recovery is initiated via RMAN, the following action is performed:
Required backup sets are identified to recover the table/partition
An auxiliary database will be configured to a pointintime temporarily in the process of recovering the table/partition
Required table/partitions will be then exported to a dumpfile using the data pumps
Optionally, you can import the table/partitions in the source database
Rename option while recovery
An example of a table pointintime recovery via RMAN (ensure you already have a full database backup from earlier):
RMAN> connect target "username/password as SYSBACKUP";
RMAN> RECOVER TABLE username.tablename UNTIL TIME 'TIMESTAMP…'
AUXILIARY DESTINATION '/u01/tablerecovery'
DATAPUMP DESTINATION '/u01/dpump'
DUMP FILE 'tablename.dmp'
NOTABLEIMPORT ‐‐ this option avoids importing the table automatically.
REMAP TABLE 'username.tablename': 'username.new_table_name'; ‐‐ can rename table with this option.
Important notes:
Ensure sufficient free space available under /u01 filesystem for auxiliary database and also to keep the data pump file
A full database backup must be exists, or at least the SYSTEM related tablespaces
The following limitations/restrictions are applied on table/partition recovery in RMAN:
SYS user table/partition can’t be recovered
Tables/partitions stored under SYSAUX and SYSTEM tablespaces can’t be recovered
Recovery of a table is not possible when REMAP option used to recovery a table that contains NOT NULL constraints
10. Restricting PGA size
Pre Oracle 12c R1, there was no option to limit and control the PGA size. Although, you set a certain size to
PGA_AGGREGATE_TARGET initialization parameter, Oracle could increase/reduce the size of the PGA dynamically based on the
workload and requirements. In 12c, you can set a hard limit on PGA by enabling the automatic PGA management, which requires
PGA_AGGREGATE_LIMIT parameter settings. Therefore, you can now set the hard limit on PGA by setting the new parameter to
avoid excessive PGA usage.
SQL> ALTER SYSTEM SET PGA_AGGREGATE_LIMIT=2G;
SQL> ALTER SYSTEM SET PGA_AGGREGATE_LIMIT=0; ‐‐disables the hard limit
Important notes:
When the current PGA limits exceeds, Oracle will automatically terminates/abort the session/process that holds the most untenable PGA
memory.
In part 2, you will learn more on new changes on Cluster, ASM, RMAN and database administration areas.
Read Oracle Database 12c New Features – Part 2
Syed Jaffar Hussain
Syed Jaffar Hussain, the Database Support Team Lead in Inma Bank, is an Oracle Certified Master (10g), Oracle ACE Director, Oracle
RAC Certified Expert and OCP v8i, v9i, v10g and v11g DBA having 20 years of Information Technology experience, which includes
over 11 years as an Oracle DBA. Over the past 9 years, he has worked as an Oracle consultant with many international clients (mostly in
the banking sector) and has been involved in several challenging projects such as implementing RAC, setting up Data Guard for all the
business critical databases, tuning databases to increase the throughput, and database migration/upgrade on various operating systems. He
recently honored by Oracle Magazine with 'DBA of the year' award for year 2011.
Comments
Trackbacks
54 Comments
1.
Rich
27/06/2013 · Reply
I find the invisible column concept very interesting. I have a few systems where some tables maintain a few different ID's for
integration purposes, but there is no need for anyone except me to know they are there.
Arif
16/04/2014 · Reply
Wonderfull effort. Keep it up with great stuff.
2.
Muhammed yunoos
27/06/2013 · Reply
great article ..thank you
3.
Shashwat
27/06/2013 · Reply
Nice article. Writing for part 2.
Anand
04/09/2014 · Reply
Nice document.
4.
Monowar Mukul
28/06/2013 · Reply
Thanks for sharing your knowledge. At this stage I think sysback, sysdg & syskm is really good features as you do not need to give
sysdba privilege.
5.
siva
28/06/2013 · Reply
HI Hussain,
excellent document.
6.
Venkat kompally
28/06/2013 · Reply
awesome tips
7.
Girish
28/06/2013 · Reply
Great article ... thanks.
Are you planning to cover architecture changes in 12C ? Specially in CDB and PDB
8.
Manzoor Hashmi
28/06/2013 · Reply
Excellent stuff ! very informative. Thanks
9.
Manzoor Hashmi
28/06/2013 · Reply
Part II is eagerly awaited.
10.
ahamed
29/06/2013 · Reply
Great Articles..
11.
29/06/2013 · Reply
Thank you for posting this Syed. It is definitely very helpful. However, I would just like to bring to your notice that DDL logging
feature was available even in 11gR2. The difference is, the DDL statements are written to alert log file in 11gR2.
FYI:
http://docs.oracle.com/cd/E11882_01/server.112/e25513/initparams084.htm
Regards,
R
Syed Jaffar Hussain
01/07/2013 · Reply
It was not quite clear about this feature in 11gR2.
Debs
09/12/2013 · Reply
Hi,
It was very much clear and we have been using for last 4 years. Not only that , you can use this with adrci as well.
12.
Diptiranjan
29/06/2013 · Reply
Superb!! One of the best blog ... Waiting for partII..
Syed Jaffar Hussain
01/07/2013 · Reply
Pretty soon Part 2 will be posted on the website.
13.
imran Khan
01/07/2013 · Reply
Assalaamualaikum Jaffer Bhai,
When moving the datafile , Do we have to copy the datafile at OS level? I did the following:
SQL> select name from v$datafile;
NAME
/oradata/SID/system01.dbf
/oradata/SID/exam03.dbf
/oradata/SID/sysaux01.dbf
/oradata/SID/undotbs01.dbf
/oradata/SID/users01.dbf
SQL> !cp exam03.dbf exam02.dbf
SQL> select name from v$datafile;
NAME
/oradata/SID/exam03.dbf
When moving it gave the following error, while the transaction at the other terminal was going on ( was inserting lacs of records
simultaneously during this operation)
SQL> alter database move datafile '/oradata/SID/exam03.dbf' to '/oradata/SID/exam02.dbf';
alter database move datafile '/oradata/SID/exam03.dbf' to '/oradata/SID/exam02.dbf'
*
ERROR at line 1:
ORA01119: error in creating database file '/oradata/SID/exam02.dbf'
ORA27038: created file already exists
Additional information: 1
SQL> select name from v$datafile;
NAME
/oradata/SID/exam03.dbf
Then in the next step it altered:
alter database move datafile '/oradata/SID/exam03.dbf' to '/oradata/SID/exam02.dbf';
Database altered.
SQL> select name from v$datafile;
NAME
/oradata/SID/exam02.dbf
I am quite confused, Could you please put some light on this.
Jazaakallah
14.
imran Khan
01/07/2013 · Reply
And also the database was in No archivelog mode.
15.
Syed Jaffar Hussain
01/07/2013 · Reply
Imran, you shouldn't be copying the file before moving. The move datafile command will do all that for you.
16.
Girish
01/07/2013 · Reply
But does move command works when database is in Noarchivelog mode and how?
17.
imran Khan
01/07/2013 · Reply
Got it... Thanks a lot Jaffer bhai... May Allah give u more knowledge..
Jazaakallah..
18.
krishna Prasad
01/07/2013 · Reply
Great!!!...thanks for sharing!!!!!
19.
Miguel
04/07/2013 · Reply
Excelent. Thanks!!!
20.
Krishna reddy
05/07/2013 · Reply
Thanks Syed .. Great article with detailed explination..
21.
Syed Jaffar Hussain
07/07/2013 · Reply
The correct syntax for a sub|partition move as follows:
ALTER TABLE emp MOVE SUB|PARTITION emp_part2 TABLESPACE data_ts UPDATE INDEXES ONLINE;
22.
Syed Jaffar Hussain
07/07/2013 · Reply
TRUNCATE|MERGE|SPLIT PARTITION{S} is synonym of TRUNCATE|MERGE|SPLIT PARTITION. Hence, you can either
refer PARTITION or PARTITIONS with the operation in the context.
23.
imran Khan
10/07/2013 · Reply
Assalaamualaikum wr wb Jafer bhai,
I have tried to move the partition using only TABLESPACE clause but it refuses since the partition type is composite:
11:47:13 SQL> alter table orders move partition ORDERS2014 to tablespace users;
alter table orders move partition ORDERS2014 to tablespace users
*
ERROR at line 1:
ORA14020: this physical attribute may not be
specified for a table partition
Elapsed: 00:00:00.01
11:47:22 SQL> !oerr ora 14020
14020, 00000, "this physical attribute may not be specified for a table partition"
// *Cause: unexpected option was encountered while parsing physical
// attributes of a table partition; valid options for Range or
// Composite Range partitions are INITRANS, MAXTRANS, TABLESPACE,
// STORAGE, PCTFREE, and PCTUSED; only TABLESPACE may be specified
// for Hash partitions
// *Action: remove invalid option(s) from the list of physical attributes
// of a table partition
// *Comment: this error could have resulted from omission of a
// terminating (right) parenthesis following the list of
// partition descriptions
Can you please put some light on the above.
Jazaakallah,
Imran Khan
24.
Diptiranjan
10/07/2013 · Reply
Hi Jaffar,
when you move the datafile you mentioned that users can continue the dml operations then how will the move work. How will the
move happen will it copy data currently being written to the datafile ?
Also is the physical copy also not required if this is done . Will the SQL copy the files also ?
Regards,
Diptiranjan
25.
Robert
10/07/2013 · Reply
I found the statement in #4 (Multiple indexes on the same column) to be misleading. It says, "a column can’t be in more than one
index in any form." The same column can be used in multiple indexes, but the same column list can only be indexed once. Given a
table with columns A and B, it is entirely possible to create two indexes that use column A. One index on column A can be
created, and a second index of the same type can be created on columns A and B.
26.
Tim Gotham
10/07/2013 · Reply
Good article and tips. Thanks for writing it.
Two notes:
1. DDL logging has been available since atleast 10gR2 it may be easier now, but I work with a DB that does ddl logging in 10g.
2. Regarding "Multiple indexes on the same column" could you be more specific here. We have many, many situations on
10g/11g where the same column appears in multiple indexes. I can understand the issue where Oracle does not allow duplicate
indexes. But the way you have it worded, it would make it seem like a single column cannot appear in the column list of more than
one index prior to 12c that is certainly false.
Thanks,
Tim
27.
Syed Jaffar Hussain
11/07/2013 · Reply
Thanks Robert & Tim.
Indeed the phrase on multiple indexes on the same columns was bit misleading. I have asked to replace with the following text:
4. Multiple indexes on the same column[s]
Pre Oracle 12c, you can't create multiple indexes either on the same column or set of columns in any form. For example, if you
have an index on column {a} or columns {a,b}, you can't create another index on the same column or set of columns in the same
order. Perhaps one might wonder why usually a column needs to be in multiple indexes. There are many reasons where you need a
column or set of columns in more than one index. In 12c, you can have multiple indexes on the same column or set of columns as
long as the index type is different. However, only one type of index is usable/visible at a given time. In order to test the invisible
indexes, you need to set the optimizer_use_use_invisible_indexes=true.
Here is the example:
SQL> CREATE INDEX emp_ind1 ON EMP(ENO,ENAME);
SQL> CREATE BITMAP INDEX emp_ind2 ON EMP(ENO,ENAME) INVISIBLE;
All Things Oracle
11/07/2013 · Reply
Thank you Robert and Tim for your feedback. Thank you Jaffar for sending your update over so quickly!
I urge more people to contribute to articles on the site, through the comments function, to share their knowledge with the
community.
28.
Rajavelu
12/07/2013 · Reply
Excellent Thanks....
29.
harihara jannu
13/07/2013 · Reply
Great article Jafar .. Can you please explain about container database and pluggable databases ?
30.
yatin
18/07/2013 · Reply
excellent work for new and middle level oracle doers.
31.
Ameerudeen
20/07/2013 · Reply
Superb Article . Thanks for sharing.
32.
Neerja
25/07/2013 · Reply
Thanks !
Good Document. Waiting for verion 2
All Things Oracle
25/07/2013 · Reply
Hi Neerja, here are links to the other parts in this series:
Read Oracle Database 12c New Features – Part 2
Read Oracle Database 12c New Features – Part 3
Read Oracle Database 12c New Features – Part 4
James
33.
Nasir Habib
27/08/2013 · Reply
Good Job Jaffer bhai :)
34.
Oracle_BUG
10/09/2013 · Reply
Nice Article and just quick reference
35.
Ayo
30/10/2013 · Reply
Nice write up, moving over to read part 2 now. Well done
36.
anil akduygu
15/11/2013 · Reply
Very good articles, thanks and we are waiting for new articles.
Anıl Akduygu from Turkey.
37.
Rohan Shinde
15/11/2013 · Reply
Hi, Thanks for sharing such nice explanation about Oracle 12c new features. I have query about pluggable database. After creating
pluggable database, can we migrate in to container database? If yes then how? Thanks for great help.
38.
Syed Shoeb ur Rahman
28/11/2013 · Reply
Asalam..Jaffar Indeed it was a very good & Informative..
Thanks
Shoeb
39.
Ashutosh Khare
29/11/2013 · Reply
I was looking for the consolidated document for the new features in 12C . Thanks for sharing ... :) :)
40.
Arun Kumar
09/01/2014 · Reply
Hi Jaffar,
I have read your articles, its really happy that i have gain some knowledge from this articles.
Thanks a lot :)
Regards,
Arun
41.
Alan Covell
01/02/2014 · Reply
Dear Sir,
I find your blog excellent. As a professional educator, I would like to make a sugestion. It would be wonderful if you could
add pictorial examples that explain how the various parts of all of Oracle fit together, as there is so much to it now, it can be
difficult to conceptualize the entire DB, rather like the famous 'Blind Men and the Elephant.'
Thanks for your time,
Alan
42.
BharathReddy
14/03/2014 · Reply
Hi Jaffar,
Its very nice article
43.
Andrew Reid
21/03/2014 · Reply
I liked the first new feature about moving datafiles so I translated it into Spanish at the URL I provided. I will try the other
examples in due course.
44.
panneer
06/09/2014 · Reply
Hi Jaffer,
Very nice article...thanks
45.
Aleem
12/09/2014 · Reply
Thanks Jaffar!!! Nice Work.
46.
sushil
16/09/2014 · Reply
Good Article !! Nicely explained in a simple language.
Thanks Jaffar!!
47.
Nagur Bhasha
09/01/2015 · Reply
Magnificient effort Hussain keep it up.
Leave a response
Name * Required
Email * Required
Website
Submit Comment
Notify me of followup comments via email. You can also subscribe without commenting.
Submit comment
Cary Millsap’s latest book
Learn all about Oracle extended SQL trace data from Cary Millsap. Includes a full chapter of case studies using Method R software.
Buy now
OakTable News
Tips on Submitting an Abstract to Conference
Little things worth knowing: what does opatchauto actually do?
Cartesian join
Demos do fail.
Good Singapore Maths Students Would Likely Make Good Oracle DBAs (Problems)
RMOUG News
Call for Nominations for the RMOUG Board Of Directors 20152016
RMOUG Big Data Special Interest Group Meetup
Thank You for Attending RMOUG Training Days 2015!
Colorado OAUG Educational Workshop
RMOUG Training Days 2015 is the One Conference You DON’T Want to Miss!
ODTUG News
#ODTUG Hosts First Ever Oracle Application Express Development Team AMA
EPM Community Newsletter
EPM Community Newsletter
Oracle OpenWorld 2015: Call for Proposals Is Now Open
Upcoming ODTUG Webinars
Categories
10g (11)
11g (45)
12c (32)
8i (3)
9i (3)
All Things Oracle Full Articles (136)
APEX (29)
Application Development (40)
Database Administration (137)
Database Development (177)
eBook (6)
EM12c (2)
Enterprise Manager (2)
Oracle Cloud (6)
Oracle Database (135)
Oracle Forms (1)
Performance Tuning (49)
PL/SQL (52)
Polls (1)
Puzzles (7)
RAC (3)
Troubleshooting (44)
Uncategorized (7)
Video (15)
Webinar (44)
Subscribe to All Things Oracle
Name:
Email:
Job Title:
Application Developer
Subscribe
© 2015 · Redgate Software and associated content authors · All Rights Reserved · Privacy policy · Terms and Conditions