Widely used classic enterprise RDBMS databases with good performance, durability and PL/SQL advanced SQL.
Most of this was not retained to be ported and I don't work on Oracle any more to go back and populate this.
- Key Points
- AWS RDS Limitations
- Install Oracle Client Packages - SQL*Plus, JDBC, ODBC, SDK
- Local Login as Admin
- Connecting to Oracle - TNS Listener & SID
- SQLcl command line client
- SQL Developer IDE
- SQL Scripts
- SQL
dual- the pseudo-table- Get Date
- Get Oracle Version
- List Tablespaces
- List Tables
- Count Tables per Tablespace
- List Users
- Show your Currently Connected Username
- Show Tables Owned by Currently Connected User
- Show the Privileges of the Currently Connected User
- Show Privileges of All Users
- Show Expired Passwords
- Alter User Password
- Show DB Configuration Parameters
- Get Table DDL
- Investigate table
- Backup Table to adjacent backup table
- Space Clean Up
- Restore table from adjacent backup table
- Troubleshooting
- Expensive
- Widely used battle tested enterprise RDBMS
- Well suited to large-scale databases
- Good performance and optimizations
- Good security and encryption
- Cloud - available on major clouds as a managed database
- PL/SQL - Procedural Language/Structured Query Language adds more programming logic as a superset of SQL
- analogous to Microsoft SQL Server's T-SQL (Transact SQL)
- Oracle Autonomous Database automates tasks like tuning, backups, and patching using machine learning
- High Availability - RAC (Real Application Clusters) and Data Guard offer high availability and disaster recovery
- Clients - SQL*Plus, SQLcl, and SQL Developer for database management and development
| Port | Description |
|---|---|
| 1521 | Oracle SQL port |
If you use Oracle on AWS RDS then you'll face the following restrictions.
Including no use of these commands:
ALTER DATABASEALTER SYSTEMCREATE ANY DIRECTORYDROP ANY DIRECTORYGRANT ANY PRIVILEGEGRANT ANY ROLE
https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html
If you have DevOps-Bash-tools you can use this automated script below.
This will give you everything - SQL*Plus, JDBC, ODBC, SDK and Tools:
install_oracle_client.shIf you get this RPM install error:
Error: Invalid version flag: or
Install an older version.
See Oracle Client Install Error in Troubleshooting section at end.
Use the rlwrap readline wrapper command in front of sqlplus to get command history:
rlwrap sqlplus <user>/<pass>@<fqdn>/<sid>This is usually available in the rlwrap package on RHEL and Debian-based Linux systems
and brew on Mac.
This bypasses all authentication and logs you in as the superuser for administer the DB without needing a password.
First su to the oracle user under which Oracle was installed:
sudo su - oracleThen as the oracle user start the local sqlplus client like this:
sqlplus / as sysdbaCheck the TNS Listener configuration for what SID the Oracle DB expects you to connect to otherwise it'll reject your
connection.
https://www.oracle.com/database/sqldeveloper/technologies/sqlcl/
Newer much more user friendly CLI client from Oracle with 100 command history buffer.
Backwards compatible CLI options with classic SQL*Plus.
- edit multi-line statements and scripts interactively at the SQLcl prompt
- native Liquibase integration, with automatic changelog generation for your Oracle Database objects
- 100 command history buffer
- auto-complete object names or keywords using the
<TAB>key - new commands:
CTAS,DLL,Repeat,ALIAS,SCRIPT,FORMATetc. - client-side scripting - execute Javascript to manipulate query results, build dynamic commands, interact with the session etc.
- supports classic SQL*Plus environment settings, commands, and behaviours
https://www.oracle.com/database/sqldeveloper/technologies/sqlcl/download/
Quickly install using DevOps-Bash-tools:
install_oracle_sqlcl.shThis will create a convenience stub script /usr/local/bin/sqlcl
pointing to /usr/local/sqlcl/bin/sql for $PATH convenience.
If you get an error running sqlcl or /usr/local/sqlcl/bin/sql like this:
Error: Could not find or load main class oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli
Caused by: java.lang.ClassNotFoundException: oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli
This rather unintuitive message is caused by the stupid installation zip having 0640 octal permissions on
sqlcl/lib/* so if installed as root normal users not in the wheel group can run the sql but it can't find the
lib/*.jar files.
If you have installed via the DevOps-Bash-tools scripted install install_oracle_sqlcl.sh you
shouldn't encounter this as it fixes the permissions at install time.
Show all settings:
show allset .../usr/local/sqlcl/bin/sql <user>/<pass>@<fqdn>/<sid>Inside SQLcl:
helpNew commands are underlined.
<TAB> autocompletes column names.
Print the DDL for a table:
ddl <schema>.<table>Options to customize DDL pretty output:
help set ddlclear screenQueries are smart formatted instead of column width to the definition like in SQL*Plus.
show sqlformatTo unset this to use the same old formatting as SQL*Plus:
set sqlformatTo output to CSV format (strings are quoted):
set sqlformat csvTurn off column headers in the output:
set header offGo back to using the nice smart formatting:
set sqlformat ansiconsoleset pagesize 50Print the history list of last remembered 100 commands:
historyGo back to command number <n> as displayed from the history command:
history <n>Execute it:
/INFO is a new version of DESCRIBE that also shows Last Analyzed date-time, rows, sample size,
if table is inmemory enabled/disabled, comments on the table,
* next to the primary key, column comments, list of indexes, foreign key referential integrity constraints:
info <table>Aliases for command queries or PL/SQL blocks with binds eg. :days:
alias listalias list tomorrowSELECT sysdate + :days from dualPrints timestamp 7 days from now:
tomorrow 7Repeat the last command 10 times, once every 1 second (useful to watch sessions and SQL queries being sent or watch the status of an index rebuild):
repeat 10 1https://www.oracle.com/database/sqldeveloper
SQL Developer - free and widely used Oracle-specific IDE.
This is better than using a generic client like DBeaver because you can use Oracle specific commands like:
SHOW PARAMETER undo_retention;which will fail on DBeaver like this:
SQL Error [900] [42000]: ORA-00900: invalid SQL statementAlternatives:
- Toad for Oracle
- Navicat for Oracle
- generic SQL Clients
Quickly from DevOps-Bash-tools:
install_oracle_sql_developer.shThis will even auto-open it for you on Mac.
On Mac you can find this in your Applications pop-up menu along with the usual programs
or you can open it from the CLI using this command:
open -a "SQLDeveloper"Hit Ctrl-Enter on Windows or Mac when the cursor is on a query in the Query Builder SQL Worksheet to
quickly execute the SQL statement (must be ended with a semi-colon ; to separate it from the next query)
without having to click the green triangle run button.
Scripts for DBA administration and performance engineering:
If you want to SELECT a value from a function or built-in value that does require querying data from a real table or view, in Oracle you need to provide a fake pseudo-table called DUAL to pass the syntax check of the SELECT query, eg. when selecting the current date (see next section for example).
SELECT SYSDATE FROM dual;SELECT * FROM v$version;Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
SELECT tablespace_name, status, contents, logging FROM dba_tablespaces;The owner is the schema, also known as the database in other RBDMS systems.
SELECT owner, table_name FROM dba_tables;SELECT
tablespace_name,
table_name,
status,
pct_used,
pct_free
FROM
all_tables
WHERE
tablespace_name NOT IN ('SYSTEM', 'SYSAUX', 'RDSADMIN')
ORDER BY
tablespace_name, table_name;SELECT
tablespace_name,
count(1) as NUM_TABLES
FROM
all_tables
GROUP BY
tablespace_name
ORDER BY
NUM_TABLES DESC;SELECT username, user_id, password, account_status, lock_date, expiry_date, profile, last_login FROM dba_users;User role assumed:
SELECT USER FROM dual;User originally connected as:
SELECT CURRENT_USER FROM dual;SELECT table_name FROM all_tables WHERE owner = USER;SELECT * FROM user_sys_privs;SELECT grantee, privilege FROM dba_sys_privs ORDER BY grantee;SELECT username, account_status FROM dba_users WHERE account_status LIKE '%EXPIRED%';ALTER USER spacewalk IDENTIFIED BY test;
-- or prompts for a new password
-- also allows for chars like ! which aren't liked on the alter user statement
--PASSWORDSELECT name, value FROM v$parameter;Without these doesn't give full show create table output:
SET PAGESIZE 0;
SET LONG 1000;SELECT dbms_metadata.get_ddl('TABLE', 'myTable', 'mySchema') FROM DUAL;SELECT MIN(row_id), MAX(row_id) FROM myTable;SELECT MIN(mycolumn), MAX(mycolumn), AVG(mycolumn) FROM myTable;Do this before any risky operations or shrinking tables:
CREATE TABLE mytable_backup AS SELECT * FROM mytable;- drop temporary and backup tables if you can
- purge recyclebin and dba recyclebin
- shrink tables / tablespaces
SHOW RECYCLEBIN;PURGE RECYCLEBIN;SHOW RECYCLEBIN;To only purge the recyclebin for a given table:
PURGE TABLE table_name;This is for all user's recyclebins.
Show the recyclebin contents for all users:
oracle_show_dba_recyclebin.sql
SELECT
owner,
object_name,
original_name,
type,
droptime,
space
FROM
dba_recyclebin
ORDER BY
owner,
droptime
DESC;Then purge it:
PURGE DBA_RECYCLEBIN;On AWS RDS you will need to call this instead due to AWS restricting some system procedures:
EXEC rdsadmin.rdsadmin_util.purge_dba_recyclebin;See this doc for more details.
Then re-run the show recyclebin query to check:
oracle_show_dba_recyclebin.sql
SELECT
owner,
object_name,
original_name,
type,
droptime,
space
FROM
dba_recyclebin
ORDER BY
owner,
droptime
DESC;These scripts calculations assume an 8KB block size, verify that using this query first:
SELECT value FROM v$parameter WHERE name = 'db_block_size';Should show value = 8192.
Show Tablespace Size, Space Used vs Free in GB and as a Percentage:
HariSekhon/SQL-scripts - oracle_tablespace_space.sql
SELECT
df.tablespace_name "Tablespace",
df.bytes / (1024 * 1024 * 1024) "Size (GB)",
(df.bytes - SUM(fs.bytes)) / (1024 * 1024 * 1024) "Used Space (GB)",
ROUND(SUM(fs.bytes) / (1024 * 1024 * 1024), 2) "Free Space (GB)",
ROUND(SUM(fs.bytes) / df.bytes * 100, 2) "Free Space %"
FROM
dba_free_space fs,
(SELECT
tablespace_name,
SUM(bytes) bytes
FROM
dba_data_files
GROUP BY
tablespace_name) df
WHERE
fs.tablespace_name (+) = df.tablespace_name
AND
UPPER(fs.tablespace_name) LIKE '%UNDO%'
GROUP BY
df.tablespace_name,
df.bytes
ORDER BY
"Free Space (GB)" DESC,
"Used Space (GB)" DESC;Show Tablespace Size, Space Used GB and Percentage Used:
HariSekhon/SQL-scripts - oracle_tablespace_space2.sql
SELECT
tablespace_name "Tablespace",
-- convert used_space in blocks to GB as each block is 8KB
ROUND(used_space * 8 / 1024 / 1024, 2) AS "Used Space (GB)",
-- convert tablespace_size in blocks to GB as each block is 8KB
ROUND(tablespace_size * 8 / 1024 / 1024, 2) AS "Total Space (GB)",
ROUND(used_percent, 2) AS "Used Space %"
FROM
dba_tablespace_usage_metrics
ORDER BY
"Used Space %" DESC;HariSekhon/SQL-scripts - oracle_table_space.sql
SELECT
owner,
table_name,
-- each block is 8KB, multiply it to GB, round to two decimal places
ROUND(blocks * 8 / 1024 / 1024, 2) AS total_gb,
-- estimate data size from rows vs average row size, round to two decimal places
ROUND(num_rows * avg_row_len / 1024 / 1024 / 1024, 2) AS actual_data_gb,
-- estimate free space by subtracting the two above calculations
ROUND((blocks * 8 / 1024 / 1024) - (num_rows * avg_row_len / 1024 / 1024 / 1024), 2) AS free_space_gb,
-- calculate free space percentage from the above three calculations
ROUND(
( (blocks * 8 / 1024 / 1024) - (num_rows * avg_row_len / 1024 / 1024 / 1024) ) /
(blocks * 8 / 1024 / 1024) * 100, 2) AS free_space_pct
FROM
dba_tables
WHERE
blocks > 0
AND
num_rows > 0
AND
((blocks * 8 / 1024 / 1024) - (num_rows * avg_row_len / 1024 / 1024 / 1024)) /
(blocks * 8 / 1024 / 1024) > 0.2 -- TUNE: currently only showing tables over 20% utilized
AND
owner NOT IN
('SYS', 'SYSTEM', 'SYSAUX', 'RDSADMIN')
ORDER BY
free_space_gb DESC,
total_gb DESC;To investigate tables space in only a given schema eg. USERS:
SELECT
t.owner,
t.table_name,
ROUND(t.blocks * 8 / 1024 / 1024, 2) AS total_gb_from_tables,
ROUND(s.bytes / 1024 / 1024 / 1024, 2) AS total_gb_from_segments,
ROUND(t.num_rows * t.avg_row_len / 1024 / 1024 / 1024, 2) AS actual_data_gb,
ROUND(((t.blocks * 8 / 1024) - (t.num_rows * t.avg_row_len / 1024 / 1024)) / 1024, 2) AS estimated_free_space_gb,
ROUND(((t.blocks * 8) - (t.num_rows * t.avg_row_len / 1024)) / (t.blocks * 8) * 100, 2) AS estimated_free_space_pct,
t.last_analyzed
FROM
dba_tables t
JOIN
dba_segments s
ON
t.owner = s.owner
AND
t.table_name = s.segment_name
WHERE
t.blocks > 0
AND
t.num_rows > 0
AND
-- TUNE: currently only showing tables over 20% utilized
((t.blocks * 8 / 1024) - (t.num_rows * t.avg_row_len / 1024 / 1024)) / (t.blocks * 8 / 1024) > 0.2
AND
t.owner = 'INFA_STG2'
ORDER BY
estimated_free_space_gb DESC,
total_gb_from_segments DESC;To investigate segments in the given schema eg. USERS:
SELECT
segment_name,
segment_type,
tablespace_name,
bytes/1024/1024/1024 AS size_gb,
blocks
FROM
dba_segments
WHERE
owner = 'USERS' -- XXX: Edit this
AND
segment_type = 'TABLE'
AND
blocks > 8
-- to look at only specific tables
-- AND
--segment_name IN
--('MY_TABLE', 'MY_TABLE2')
ORDER BY
size_gb DESC;Find table candidates to move / shrink in a given tablespace:
SELECT
segment_name,
segment_type,
ROUND(SUM(bytes)/1024/1024/1024, 2) AS size_gb
FROM
dba_segments
WHERE
tablespace_name = 'USERS' -- XXX: Edit
GROUP BY
segment_name,
segment_type
HAVING
SUM(bytes)/1024/1024/1024 > 1
ORDER BY
size_gb DESC;First backup the table you are going to shrink to an adjacent backup table.
Then SHRINK SPACE of the table to reduce space allocated to it by removing unused space from its data blocks
(optimizes storage and improves performance).
ALTER TABLE mytable ENABLE ROW MOVEMENT;CASCADE also shrinks dependent objects eg. indexes:
ALTER TABLE mytable SHRINK SPACE CASCADE;--Start time Thu Oct 10 13:56:13 GST 2024
--Finish time Thu Oct 10 14:01:10 GST 2024
ALTER TABLE mytable DISABLE ROW MOVEMENT;Regenerate stats on table otherwise you won't see the space change:
CALL DBMS_STATS.GATHER_TABLE_STATS('myschema', 'mytable');Check the space again by running scripts / queries above in HariSekhon/SQL-scripts.
Investigate table to check it looks ok.
If happy, then drop the backup table:
DROP TABLE mytable_backup;Rollback if any problem following Restore table from adjacent backup table.
On AWS RDS follow this doc and this doc.
ALTER TABLESPACE users COALESCE;ALTER TABLESPACE users RESIZE 500G;SQL Error [3297] [42000]: ORA-03297: file contains used data beyond requested RESIZE value
Add new temp tablespace and then remove old one:
CREATE TEMPORARY TABLESPACE
temp2
TEMPFILE '/path/to/new_tempfile.dbf'
SIZE 50G REUSE
AUTOEXTEND ON NEXT 1G MAXSIZE 500G;Switch default tempspace to the new one:
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp2;Switch all users tempspaces to the new one:
BEGIN
FOR r IN (SELECT username FROM dba_users WHERE temporary_tablespace = 'TEMP') LOOP
EXECUTE IMMEDIATE 'ALTER USER ' || r.username || ' TEMPORARY TABLESPACE temp2';
END LOOP;
END;
/Wait for old user sessions to complete:
SELECT
username, tablespace, blocks
FROM
v$tempseg_usage
WHERE
tablespace = 'TEMP';Then drop the old temp tablespace:
DROP TABLESPACE TEMP INCLUDING CONTENTS AND DATAFILES;Create new temporary tablespace tempfile with a new size first to avoid Oracle having any period of time with no sort / index rebuild space:
ALTER TABLESPACE temp ADD TEMPFILE '/path/to/new_tempfile.dbf' SIZE 1000M;Find the path to the old tempfile:
SELECT file_name, tablespace_name, bytes/1024/1024 AS size_mb FROM v$tempfile;or
SELECT file_name, tablespace_name, bytes/1024/1024 AS size_mb FROM dba_temp_files;Edit the filename path in this ALTER statement to delete that tempfile when no session is using the temp tablespace:
ALTER DATABASE TEMPFILE '/path/to/old_tempfile.dbf' DROP;If this is overallocated you can drop and create it smaller.
Use this query to find out if it's a Bigfile or Smallfile tablespace. AWS RDS uses Bigfile tablespaces.
SELECT TABLESPACE_NAME, CONTENTS, BIGFILE FROM DBA_TABLESPACES;WARNING: dropping temp tablespace or tablespace file can disrupt active sessions using sorts, large queries, or index rebuilds, all of which use the temporary tablespace and can get hit with errors like:
ORA-01187: cannot read from file because it failed verification tests
or
ORA-01110: data file name of the tempfile
You should add a new temp tablespace for a bigfile tablespace or add a new temp tablespace datafile for smallfile tablespace.
Check for a low activity time and that there are no currently active sessions using temp tablespace before dropping the old temporary file.
Show User Sessions Using Temporary Tablespace:
HariSekhon/SQL-scripts - oracle_show_sessions_using_temp_tablespace.sql
SELECT
s.sid,
s.username,
t.tablespace,
t.blocks,
t.segfile#,
t.segblk#,
t.contents,
t.sql_id
FROM
v$sort_usage t,
v$session s
WHERE
t.session_addr = s.saddr;You cannot shrink it but must replace it with a smaller one.
Check how long your Undo retention is:
SHOW PARAMETER undo_retention;This is in seconds, ie. 15 minutes:
NAME TYPE VALUE
-------------- ------- -----
undo_retention integer 900
Create a new smaller 'undo' tablespace:
CREATE UNDO TABLESPACE new_undo_ts DATAFILE SIZE 100G AUTOEXTEND ON NEXT 1G MAXSIZE 500G;Switch to the new undo tablespace.
On AWS RDS this is actually quite a bit problem since the ALTER SYSTEM command is not allowed
and therefore requires a database restart.
Set system to use new undo tablespace:
ALTER SYSTEM SET UNDO_TABLESPACE = new_undo_ts;Important*: Wait until no active connections is using the old UNDO tablespace:
SELECT tablespace_name FROM dba_tablespaces WHERE contents = 'UNDO';only then drop the old undo tablespace:
You can reduce the Undo Retention period like this to try to expedite this:
ALTER SYSTEM SET undo_retention = 900; -- Set to 15 minutes temporarilyOnce there is nothing using it, drop the old undo tablespace:
DROP TABLESPACE old_undo_ts INCLUDING CONTENTS AND DATAFILES;First check you have the backup table mytable_backup.
Once backup table contents has been verified, then empty the table to be restored:
TRUNCATE TABLE mytable;Then restore the rows from the backup table:
INSERT INTO mytable SELECT * FROM mytable_backup;This happens on Amazon Linux 2 with the latest Oracle Client version 23.
Workaround: Install Oracle Client 21 instead.
If you get an error running sqlcl or /usr/local/sqlcl/bin/sql like this:
Error: Could not find or load main class oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli
Caused by: java.lang.ClassNotFoundException: oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli
This rather unintuitive message is caused by the stupid installation zip having 0640 octal permissions on
sqlcl/lib/* so if installed as root normal users not in the wheel group can run the sql but it can't find the
lib/*.jar files.
Fix:
chmod -R o+r /usr/local/sqlcl/libIf you have installed via the DevOps-Bash-tools scripted install install_oracle_sqlcl.sh you
shouldn't encounter this as it fixes the permissions at install time.
Partial dump from memory because I didn't have many notes retained from my Oracle DBA time in 2005-2009