60

How can I find the table creation time in PostgreSQL?

Example: If I created a file I can find the file creation time like that I want to know the table creation time.

funnydman
  • 9,083
  • 4
  • 40
  • 55
kiruthika
  • 2,155
  • 7
  • 26
  • 33

9 Answers9

27

I had a look through the pg_* tables, and I couldn't find any creation times in there. It's possible to locate the table files, but then on Linux you can't get file creation time. So I think the answer is that you can only find this information on Windows, using the following steps:

  • get the database id with select datname, datdba from pg_database;
  • get the table filenode id with select relname, relfilenode from pg_class;
  • find the table file and look up its creation time; I think the location should be something like <PostgreSQL folder>/main/base/<database id>/<table filenode id> (not sure what it is on Windows).
Alex Korban
  • 14,916
  • 5
  • 44
  • 55
  • 7
    There are some operations on a table, such as CLUSTER, that will generate a new file and not re-use the old one. So this is not a reliable method. – Magnus Hagander Apr 05 '10 at 09:15
  • 1
    @Alex Korban: Fully automatized this here: http://stackoverflow.com/questions/18849756/automatically-drop-tables-and-indexes-older-than-90-days/18852752#18852752 – Stefan Steiger Sep 17 '13 at 15:09
  • @Quandary: Interesting, thanks. Looks like there's still no bulletproof method to do it, other than storing creation times yourself. – Alex Korban Sep 19 '13 at 04:42
  • I need to be a master user? Can you express a are a query (that works), like the @Manoj's? – Peter Krauss Jan 13 '14 at 00:01
  • Have a look at @Quandary's link: http://stackoverflow.com/questions/18849756/automatically-drop-tables-and-indexes-older-than-90-days/18852752#18852752 – Alex Korban Jan 13 '14 at 04:07
  • Great answer. Something I have been looking around for sometime. Further, SELECT oid from pg_database WHERE datname = ‘’ will give the database folder name within the base folder that holds all the databases – picmate 涅 Jun 10 '15 at 15:52
  • For future searchers, it is possible to determine an upper bound of the table creation time, which may be sufficient for some use cases. (That is, you can say, "The table was created no later than the creation timestamp of the table file.") – khstacking Jan 14 '20 at 22:28
24

You can't - the information isn't recorded anywhere. Looking at the table files won't necessarily give you the right information - there are table operations that will create a new file for you, in which case the date would reset.

Magnus Hagander
  • 23,890
  • 5
  • 56
  • 43
  • 1
    Do you know which table operations create a new file? Is that renaming tables? Or adding fields? Knowing the history of the table and which operations create a new file I could at least guestimate the creation time. – kramer65 Jul 23 '19 at 08:53
3

I don't think it's possible from within PostgreSQL, but you'll probably find it in the underlying table file's creation time.

Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
2

Suggested here :

SELECT oid FROM pg_database WHERE datname = 'mydb';

Then (assuming the oid is 12345) :

ls -l $PGDATA/base/12345/PG_VERSION

This workaround assumes that PG_VERSION is the least likely to be modified after the creation.

NB : If PGDATA is not defined, check Where does PostgreSQL store the database?

Community
  • 1
  • 1
Skippy le Grand Gourou
  • 6,976
  • 4
  • 60
  • 76
1
  1. Check data dir location SHOW data_directory;
  2. Check For Postgres relation file path : SELECT pg_relation_filepath('table_name'); you will get the file path of your relation
  3. check for creation time of this file <data-dir>/<relation-file-path>
0

I tried a different approach to get table creation date which could help for keeping track of dynamically created tables. Suppose you have a table inventory in your database where you manage to save the creation date of the tables.

CREATE TABLE inventory (id SERIAL, tablename CHARACTER VARYING (128), created_at DATE);

Then, when a table you want to keep track of is created it's added in your inventory.

CREATE TABLE temp_table_1 (id SERIAL); -- A dynamic table is created
INSERT INTO inventory VALUES (1, 'temp_table_1', '2020-10-07 10:00:00'); -- We add it into the inventory

Then you could get advantage of pg_tables to run something like this to get existing table creation dates:

    SELECT pg_tables.tablename, inventory.created_at
      FROM pg_tables
INNER JOIN inventory
        ON pg_tables.tablename = inventory.tablename

/*
  tablename   | created_at 
--------------+------------
 temp_table_1 | 2020-10-07
*/

For my use-case it is ok because I work with a set of dynamic tables that I need to keep track of.

P.S: Replace inventory in the database with your table name.

  • relation "inventory" does not exist LINE 3: INNER JOIN inventory – Prasad Lele Dec 04 '19 at 12:04
  • @PrasadLele it's not supposed to work with copy&paste. As I mentioned, "Suppose you have a table `inventory` in your database"... If you don't have a table `inventory` created it will obviously fail. You need to replace `inventory` in the query with your table name. I would appreciate if you remove your negative vote having clarified this. – Jaume Jiménez Dec 05 '19 at 13:08
  • I've replaced inventory to my table name but it doesn't work anyway. – Dennis V Sep 21 '20 at 06:05
  • Can you give more information about the error @DennisV.R. ? – Jaume Jiménez Sep 22 '20 at 08:32
  • @JaumeJiménez example with my PostgreSQL 9.6 https://pastebin.com/raw/ckus87RX – Dennis V Oct 01 '20 at 14:01
  • @DennisV.R. I may explained poorly the case. The use case for this solution needs a table `inventory` which keeps track of the tables when they are created, so it's a table with columns (`id`, `tablename`, `created_at`). The snippet was not meant to be a copy & paste, it has to fit in your use case. I' have edited the answer so I hope it can help you now. – Jaume Jiménez Oct 07 '20 at 13:57
-1

I'm trying to follow a different way for obtain this. Starting from this discussion my solution was:

DROP TABLE IF EXISTS t_create_history CASCADE;
CREATE TABLE t_create_history (
    gid serial primary key,
    object_type varchar(20),
    schema_name varchar(50),
    object_identity varchar(200),
    creation_date timestamp without time zone 
    );



--delete event trigger before dropping function
DROP EVENT TRIGGER IF EXISTS t_create_history_trigger;

--create history function
DROP FUNCTION IF EXISTS public.t_create_history_func();

CREATE OR REPLACE FUNCTION t_create_history_func()
RETURNS event_trigger
LANGUAGE plpgsql
AS $$
DECLARE
    obj record;
BEGIN
    FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands  () WHERE command_tag in ('SELECT INTO','CREATE TABLE','CREATE TABLE AS')
    LOOP
        INSERT INTO public.t_create_history (object_type, schema_name, object_identity, creation_date) SELECT obj.object_type, obj.schema_name, obj.object_identity, now();
    END LOOP; 

END;
$$;


--ALTER EVENT TRIGGER t_create_history_trigger DISABLE;
--DROP EVENT TRIGGER t_create_history_trigger;

CREATE EVENT TRIGGER t_create_history_trigger ON ddl_command_end
WHEN TAG IN ('SELECT INTO','CREATE TABLE','CREATE TABLE AS')
EXECUTE PROCEDURE t_create_history_func();

In this way you obtain a table that records all the creation tables.

-4

--query

select pslo.stasubtype, pc.relname, pslo.statime
from pg_stat_last_operation pslo
join pg_class pc on(pc.relfilenode = pslo.objid)
and pslo.staactionname = 'CREATE'
Order By pslo.statime desc 

will help to accomplish desired results

(tried it on greenplum)

-5

You can get this from pg_stat_last_operation. Here is how to do it:

select * from pg_stat_last_operation where objid = 'table_name'::regclass order by statime;

This table stores following operations:

select distinct staactionname from pg_stat_last_operation;

 staactionname 
---------------
 ALTER

 ANALYZE

 CREATE

 PARTITION

 PRIVILEGE

 VACUUM
(6 rows)
tessi
  • 13,313
  • 3
  • 38
  • 50
Manoj
  • 15
  • 1