Thursday, November 20, 2025

How to unload rows in an Oracle database to disk using sqlcl

In sqlcl, execute these lines to unload SCOTT.EMP to disk:
set arraysize 200
set load batch_rows 200
UNLOAD TABLE SCOTT.EMP DIR /datadisk1/export
Do not use semicolon after the end of the command!

Find total size of all databases in PostgreSQL cluster

SELECT database, size FROM (
  SELECT datname AS database,
         pg_size_pretty(pg_database_size(datname)) AS size,
         0 AS sort_order
  FROM pg_database
  UNION ALL
  SELECT 'TOTAL',
         pg_size_pretty(SUM(pg_database_size(datname))),
         1
  FROM pg_database
) AS sub
ORDER BY sort_order, size DESC;
Example output:
             database             |  size
----------------------------------+---------
 mydb01                           | 7819 kB
 mydb02                           | 7795 kB
 postgres                         | 7739 kB
 template0                        | 7731 kB
 template1                        | 7715 kB
 proddb01                         | 76 GB
 proddb02                         | 2971 GB
 proddb03                         | 22 GB
 warehouse01                      | 11 TB
 testdb01                         | 106 MB
 TOTAL                            | 14 TB
(11 rows)

Monday, November 17, 2025

Tuesday, November 11, 2025

Exchange all occurences of a string in all files in a sub-directory structure

find /var/lib/pgsql/cities/aberdeen/schema -type f -exec sed -i 's/aberdeen/glascow/g' {} +

List all files containg a string in a subdirectory structure

grep -Rl 'aberdeen' /var/lib/pgsql/cities/aberdeen/schema
Result:
/var/lib/pgsql/cities/aberdeen/schema/grants/grant.sql
/var/lib/pgsql/cities/aberdeen/schema/sequences/sequence.sql
/var/lib/pgsql/cities/aberdeen/schema/sequence_values/sequence_value.sql
/var/lib/pgsql/cities/aberdeen/schema/tables/table.sql
/var/lib/pgsql/cities/aberdeen/schema/tables/AUTOINCREMENT_table.sql
/var/lib/pgsql/cities/aberdeen/schema/tablespaces/tablespace.sql
/var/lib/pgsql/cities/aberdeen/schema/triggers/trigger.sql
/var/lib/pgsql/cities/aberdeen/schema/views/view.sql

Monday, November 10, 2025

Generate truncate table statements in PostgreSQL

To generate a script in postgreSQL, equivalent to the Oracle-style shown below:
select 'truncate table ' || table_name || ' cascade;' from dba_tables where owner='MYSCHEMA';
, put this in a file called gen_truncate.sql
/*
| Setting                  | Effect                                                    |
| ------------------------ | --------------------------------------------------------- |
| `\o /path/to/file`       | Redirects all query output to the file                    |
| `\pset format unaligned` | Produces plain text output (no table formatting)          |
| `\pset tuples_only on`   | Suppresses headers and row counts                         |
| `\pset footer off`       | Removes `x rows` footer                                   |
| `\pset border 0`         | Removes any border formatting (mostly for aligned format) |
*/

\o truncate_tables.sql
\pset format unaligned
\pset tuples_only on
\pset footer off
\pset border 0
SELECT 'TRUNCATE TABLE ' || schemaname || '.' || tablename || ' CASCADE;' AS stmt
FROM pg_tables
WHERE schemaname = 'myschema';
\o
Execute it:
psql mydb -f gen_truncate.sql
or login to the desired database directly as the owner of the table:
psql -h localhost -d mydb -U myuser -f gen_truncate.sql

Do I need special privileges to create temporary tables in a database in PostgreSQL?

To verify if your user has the privilege to create temporary segments in a postgreSQL database, use this check:
psql -h localhost -d mydb -U myuser

 SELECT has_database_privilege(current_user, current_database(), 'TEMP');
If the value returned shows:
has_database_privilege
------------------------
 f
To be able to create a temporary table in this database, my user needs privileges to do so:
psql
postgres=# grant temp on database mydb to myser;
GRANT
The same test will now yield true instead of false:
SELECT has_database_privilege(current_user, current_database(), 'TEMP');
 has_database_privilege
------------------------
 t
(1 row)
I can now create a temporary table:
CREATE TEMP TABLE table_counts (table_name text, row_count bigint);
Before the grant, the access privileges for my database was
mydb=> \l+ mydb

  |      Access privileges       |
  +------------------------------+
  | postgres=CTc/postgres       +|
  | myuser=c/postgres           +|
 
After the grant:
  |      Access privileges       |
  +------------------------------+
  | postgres=CTc/postgres       +|
  | myuser=Tc/postgres          +|
Notice how the privileges for "myuser" has a "T" ammended to it. This indicate the permission to create temporary objects.

Friday, October 31, 2025

PostgreSQL query that mimics Oracle's DBA_OBJECTS aggregation

with base_objects as (
  select 
    case 
      when c.relkind = 'r' then 'TABLE'
      when c.relkind = 'v' then 'VIEW'
      when c.relkind = 'm' then 'MATERIALIZED VIEW'
      when c.relkind = 'i' then 'INDEX'
      when c.relkind = 'S' then 'SEQUENCE'
      when c.relkind = 'f' then 'FOREIGN TABLE'
      when c.relkind = 'p' then 'PARTITIONED TABLE'
      when c.relkind = 'I' then 'PARTITIONED INDEX'
      else 'OTHER'
    end as object_type
  from pg_class c
  join pg_namespace n on n.oid = c.relnamespace
  where n.nspname = 'myschema'

  union all

  select 
    case p.prokind
      when 'f' then 'FUNCTION'
      when 'p' then 'PROCEDURE'
      when 'a' then 'AGGREGATE'
      when 'w' then 'WINDOW'
      else 'OTHER'
    end as object_type
  from pg_proc p
  join pg_namespace n on n.oid = p.pronamespace
  where n.nspname = 'myschema'

  union all
  select 'TYPE'
  from pg_type t
  join pg_namespace n on n.oid = t.typnamespace
  where n.nspname = 'myschema'
    and t.typtype in ('c', 'e', 'd') -- composite, enum, domain

  union all

  select 'CONSTRAINT'
  from pg_constraint c
  join pg_namespace n on n.oid = c.connamespace
  where n.nspname = 'myschema'
)

select object_type, count(*)
from base_objects
group by object_type
order by object_type;

Thursday, October 9, 2025

How to delete all lines above and below the current line in the text editor vi

In vi (or vim), you can delete all lines above the current line with this one simple command:
:1,.−1d
To delete all rows above the current lin, press d (delete) followed by capital G (end of document):
d + G

Monday, October 6, 2025

How to check if your EBS system is on AD/TXK Delta 13

SELECT bug_number, creation_date
FROM   ad_bugs
WHERE  bug_number IN (
  -- AD/TXK Delta 13 driver patch numbers
  '35163625','35163283','35163924','35162879'
)
ORDER BY creation_date DESC;
If no rows are returned, you are not on AD/TXK Delta 13, yet

Monday, September 29, 2025

How to pass parameters to a psql script

To use variables in your sql script, use the -v option to set variables on the command line.

Consider this example:
export PGPASSWORD=mysecretpassword
psql -h myserver.oric.no -d db01 -U scott -v schema=scott -v table=mytable -f myquery.sql
The query in myquery.sql can then referance the "schema" and "table" variables, like this:
SELECT
    att.attname AS column_name
FROM
    pg_attribute att
JOIN
    pg_class cls ON cls.oid = att.attrelid
JOIN
    pg_namespace ns ON ns.oid = cls.relnamespace
WHERE
    ns.nspname = :'schema'
    AND cls.relname = :'table'
    AND att.attnotnull
    AND att.attnum > 0
    AND NOT att.attisdropped;

Thursday, September 25, 2025

Find out if a constraint in PostgreSQL is defined as deferrable

Logged into the relevant database, find out which FK are deferrable:
SELECT conname, condeferrable, condeferred
FROM pg_constraint
WHERE conrelid in ( 'mytable1'::regclass,'mytable2'::regclass) 
AND contype='f';
           conname            | condeferrable | condeferred
------------------------------+---------------+-------------
 mytable1_id_fkey             | f             | f
 mytable1_id_fkey             | f             | f
 mytable2_id_fkey             | f             | f
  • If condeferrable = t (true), the constraint is created initially deferrable
  • If condeferrable = f (false), like in my case, it is not.
  • Wednesday, September 24, 2025

    Terminate PostgresSQL sessions

    -- Terminate all connections from user "sales"
    SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE usename = 'sales';
    
    In my case the result was:
     pg_terminate_backend
    ----------------------
     t
     t
    (2 rows)
    

    Check active sessions in PostgreSQL

    The closest equivalent to this oracle query:
    SELECT USERNAME, COUNT(*) 
    FROM v$session 
    WHERE type <> 'BACKGROUND' 
    GROUP BY username;
    
    Would be
    SELECT datname, usename AS username, COUNT(*)
    FROM pg_stat_activity
    WHERE backend_type = 'client backend'
    GROUP BY datname, usename
    ORDER BY datname, usename;
    
    Example output:
     datname  |     username      | count
    ----------+-------------------+-------
     postgres | postgres          |     1
     postgres | postgres_exporter |     1
     mydb     | myser             |     2
    (3 rows)
    

    Thursday, September 18, 2025

    Convert all contents in a file to lower case using vim

    Open your file in vi
    vi myfile
    
    Press the escape key to enter interactive mode, then type
    :%s/.*/\L&/
    
    Press escape, then save + exit the editor:
    :wq
    

    Tuesday, September 9, 2025

    How to set echo in a SQL script executed in psql

    Use one of two options 1. in the sql file, add the following directive
    \set ECHO queries
    
    2. execute the script using the -e flag
    psql -e -f myfile.sql
    

    Monday, September 8, 2025

    Syntax for drop/recreate of constraints in PostgreSQL

    1. Find the constraints belonging to a specific table:
    SELECT conname
    FROM pg_constraint
    WHERE conrelid = 'mytable'::regclass;
        conname
    ----------------
     sys_c002733781
     sys_c002733782
    (2 rows)
    
    2. Drop them:
    ALTER TABLE mytable DROP CONSTRAINT sys_c002733781;
    ALTER TABLE
    ALTER TABLE mytable DROP CONSTRAINT sys_c002733782;
    ALTER TABLE
    
    3. Load your data using your preferred method

    4. Recreate the FK constraints but skip validating existing data (only new inserts/updates are checked):
    alter table mytable add constraint sys_c002733781 foreign key(job_id) references jobs(id) on delete cascade not valid;
    ALTER TABLE
    
    alter table mytable add constraint sys_c002733782 foreign key(task_id) references tasks(id) on delete cascade not valid;
    ALTER TABLE
    
    5. Validate constraints:
    alter table mytable validate constraint sys_c002733781;
    ALTER TABLE
    alter table mytable validate constraint sys_c002733782;
    ALTER TABLE
    

    Friday, September 5, 2025

    Query equivalent to SELECT * FROM USER_OBJECTS in PostgreSQL

    SELECT schema_name, object_name, object_type
    FROM (
        -- Tables, Views, Indexes, etc.
        SELECT
            n.nspname AS schema_name,
            c.relname AS object_name,
            CASE c.relkind
                WHEN 'r' THEN 'TABLE'
                WHEN 'v' THEN 'VIEW'
                WHEN 'm' THEN 'MATERIALIZED VIEW'
                WHEN 'i' THEN 'INDEX'
                WHEN 'S' THEN 'SEQUENCE'
                WHEN 'f' THEN 'FOREIGN TABLE'
                WHEN 'p' THEN 'PARTITIONED TABLE'
                WHEN 'I' THEN 'PARTITIONED INDEX'
                ELSE c.relkind::text
            END AS object_type
        FROM pg_class c
        JOIN pg_namespace n ON n.oid = c.relnamespace
        WHERE n.nspname = current_schema()
    
        UNION ALL
    
        -- Functions
        SELECT
            n.nspname AS schema_name,
            p.proname AS object_name,
            'FUNCTION' AS object_type
        FROM pg_proc p
        JOIN pg_namespace n ON n.oid = p.pronamespace
        WHERE n.nspname = current_schema()
    ) AS objects
    ORDER BY object_type, object_name;
    
    It only shows objects in the current schema (like Oracle USER_OBJECTS).

    If you want all objects the user owns (across schemas), replace
    WHERE n.nspname = current_schema()
    
    with
    WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
    

    Thursday, August 28, 2025

    Spool out all parameters from a datafile to a file

    psql -h postgres01.oric.no -U mysuperuser postgres -c "COPY (SELECT name || '='  || setting FROM pg_settings ORDER BY name) TO STDOUT WITH CSV HEADER"   > pg_config.csv
    

    Wednesday, August 27, 2025

    List a table, its partitions and the number of rows it contains

    SELECT
        s.schemaname,
        s.relname AS table_name,
        s.n_live_tup,
        s.last_analyze,
        s.last_autoanalyze
    FROM
        pg_stat_all_tables s
    JOIN
        pg_class c ON c.relname = s.relname
    LEFT JOIN
        pg_inherits i ON i.inhrelid = c.oid OR i.inhparent = c.oid
    WHERE
        s.schemaname = 'myschema'
        AND (
            s.relname = 'mytable'
            OR c.oid IN (
                SELECT inhrelid
                FROM pg_inherits
                WHERE inhparent = (
                    SELECT oid FROM pg_class WHERE relname = 'mytable'
                )
            )
        )
    ORDER BY
     s.n_live_tup DESC,s.last_analyze;
    
    
    Example output
    
     schemaname      |  table_name     | n_live_tup | last_analyze   		| last_autoanalyze 
    -----------------+-----------------+------------+-------------------------------+------------------------------
     myschema 	 | mytable_2015_02 |   95788115 | 2025-08-06 12:58:22.952592+00 | 
     myschema 	 | mytable_2015_03 |   78505350 | 2025-08-06 12:58:37.147433+00 | 
     myschema 	 | mytable_2015_04 |   71211253 | 2025-08-06 12:58:51.311452+00 | 
     myschema 	 | mytable_2015_01 |   68255510 | 2025-08-06 12:58:08.42708+00  | 
     myschema 	 | mytable_2015_05 |   62075043 | 2025-08-06 12:59:05.434118+00 | 
     myschema 	 | mytable_2015_06 |   60888876 | 2025-08-06 12:59:19.918657+00 | 2025-08-06 11:31:19.551345+00
     myschema 	 | mytable_2015_12 |   57485594 | 2025-08-06 13:00:43.112316+00 | 2025-08-27 03:13:11.394606+00
     myschema 	 | mytable_2016_01 |   57405307 | 2025-08-06 13:00:55.395113+00 | 2025-08-25 13:35:07.749773+00