sqlpostgresqladvantage-database-server

Can I remove a table from a schema without physically deleting it and then add it back to a schema?


I have an application that utilizes Advantage Database Server, and I want to migrate it to PostgreSQL. To remove a table from the database dictionary, I use the following SQL query:

DROP TABLE table_name FROM DATABASE NO_DELETE;

The NO_DELETE keyword instructs the server not to delete the table files from the disk. After that, I can re-add the deleted table to the database dictionary using the following procedure:

sp_AddTableToDatabase(
  TableName,CHARACTER,200,
  TablePath,CHARACTER,515,
  TableType,SHORTINT,
  CharType,SHORTINT,
  IndexFiles,MEMO,
  Comment,MEMO )

For example:

EXECUTE PROCEDURE sp_AddTableToDatabase('table_name', 'table_name.adt', 3, 1, '', '');

Is there such a possibility in PostgreSQL?


Solution

  • Move it to another schema

    If you need to temporarily "hide" it, you can just move it to a different, non-default schema/namespace:
    demo at db<>fiddle

    create schema some_other_schema;
    alter table table_name set schema some_other_schema;
    

    By default things are created and searched in schema public or whatever schema Postgres sees first in your search_path which means that once you move it elsewhere, it's no longer accessible by anyone unless they explicitly reference it by a fully schema-qualified name.

    That should be enough to hide it but to make it truly inaccessible even to those that discover its new location, you can also revoke access to it.

    To bring back the table, you can move it back to public:

    alter table some_other_schema.table_name set schema public;
    

    And if you also revoked access, you can grant it back.

    If you wanted all referential constraints to be broken in the process, possibly to cascade the drop to other objects before bringing this one back, this won't do that. Changing the namespace doesn't affect referential integrity so all foreign keys still point at this table.

    Changing schema is a metadata-only operation and will not cause any sort of actual deletion or re-write of the table's pages on disk.

    It's worth pointing out that some other RDBMS refer to databases as schemas and namespaces or vice versa. In PostgreSQL, you can have multiple schemas inside a single database and different objects can have the same identifier/name as long as they are in a different schema.


    Detach it

    If you make it a partitioned table, you can alter table..detach the partition(s), then drop the table. All referential constraints will be broken and the drop will be able to cascade while your actual data in the detached partition remains untouched.

    create table your_table
     ( id int primary key
      ,payload text)partition by range(id);
    create table your_table_partition partition of your_table default;
    alter table your_table detach partition your_table_partition;
    drop table your_table cascade;--doesn't affect your_table_partition
    

    Afterwards, you can re-define the table and re-attach the partition(s). All of this is also metdata-only and (except for the cascaded part) doesn't physically delete any rows from table's pages on disk.

    create table your_table
     ( id int primary key
      ,payload text)partition by range(id);
    alter table your_table attach partition your_table_partition default;
    

    Drop as a foreign object

    As mentioned by @Adel Alaa, you can set up the table as a foreign table. If you set it up on a Postgres db, you can use postgres_fdw to link it.

    create extension postgres_fdw;
    create server linked_local
      foreign data wrapper postgres_fdw;--no options, defaults to all local
    create user mapping for current_role
      server linked_local;--again, all defaults
    create foreign table f_your_table
     ( id int
      ,payload text)
      server linked_local
      options( schema_name 'public'
              ,table_name 'your_table');
    

    In that case, dropping it means just removing the link to the data, rather than actually removing the data from wherever it actually resides.

    insert into f_your_table values(1,'first record inserted via fdw');
    insert into your_table values(2,'second record inserted directly');
    drop foreign table f_your_table;--dropping foreign table
    

    The drop didn't remove the data at its source:

    select * from your_table;
    
    id payload
    1 first record inserted via fdw
    2 second record inserted directly

    There's file_fdw for things like CSV, extensions that let you link objects from other RDBMS, and many others.