PostgreSQL Equivalent of MySQL’s SHOW CREATE TABLE: Retrieving Table Definition DDL


2 views

When working with database migrations or remote server synchronization, developers often need to retrieve the exact DDL (Data Definition Language) statements used to create tables. MySQL users are familiar with the convenient SHOW CREATE TABLE command, but PostgreSQL requires a different approach.

PostgreSQL doesn't have a direct SHOW CREATE TABLE equivalent, but offers several powerful alternatives:


-- Using psql meta-command
\\d+ table_name

-- Using pg_dump utility
pg_dump -t table_name --schema-only database_name

-- Querying information_schema
SELECT column_name, data_type, character_maximum_length
FROM information_schema.columns
WHERE table_name = 'your_table';

For a complete solution similar to MySQL's output, create this function:


CREATE OR REPLACE FUNCTION show_create_table(p_table_name text) RETURNS text AS $$
DECLARE
    v_ddl text;
    v_tmp text;
    v_primary_keys text;
BEGIN
    -- Get table DDL
    SELECT pg_get_tabledef(table_schema, table_name) INTO v_ddl
    FROM information_schema.tables
    WHERE table_name = p_table_name;
    
    -- Get primary keys
    SELECT string_agg(column_name, ', ') INTO v_primary_keys
    FROM information_schema.key_column_usage
    WHERE table_name = p_table_name
    AND constraint_name LIKE '%_pkey';
    
    -- Get indexes
    FOR v_tmp IN 
        SELECT pg_get_indexdef(indexrelid) 
        FROM pg_index 
        WHERE indrelid = (p_table_name)::regclass
        AND indisprimary = false
    LOOP
        v_ddl := v_ddl || E';\n' || v_tmp;
    END LOOP;
    
    -- Add primary key if not already in DDL
    IF position('PRIMARY KEY' in v_ddl) = 0 AND v_primary_keys IS NOT NULL THEN
        v_ddl := v_ddl || E';\nALTER TABLE ' || p_table_name || 
                E' ADD PRIMARY KEY (' || v_primary_keys || ')';
    END IF;
    
    RETURN v_ddl;
END;
$$ LANGUAGE plpgsql;

Here's how to use these methods in real-world scenarios:


-- For a specific table
SELECT show_create_table('users');

-- For all tables in a schema
SELECT show_create_table(table_name) 
FROM information_schema.tables 
WHERE table_schema = 'public';

When working with complex PostgreSQL features, you might need additional queries:


-- Get table constraints
SELECT conname, pg_get_constraintdef(oid) 
FROM pg_constraint 
WHERE conrelid = 'your_table'::regclass;

-- Get table permissions
SELECT grantee, privilege_type 
FROM information_schema.role_table_grants 
WHERE table_name = 'your_table';

When working with database migrations or remote server synchronization, developers often need to obtain the exact CREATE TABLE statement used to define a table's structure. In MySQL, this is straightforward with the SHOW CREATE TABLE command, but PostgreSQL requires a different approach.

PostgreSQL provides several ways to retrieve table definitions:

-- Using pg_dump for a single table
pg_dump -t your_table_name your_database_name

-- Using psql meta-commands
\dt+ your_table_name
\d+ your_table_name

For programmatic access within PostgreSQL, these methods work best:

-- Using pg_get_tabledef function (if available)
SELECT pg_get_tabledef('your_schema', 'your_table');

-- Alternative using information_schema
SELECT 
    'CREATE TABLE ' || table_name || ' (' || 
    string_agg(column_name || ' ' || data_type || 
    CASE WHEN character_maximum_length IS NOT NULL 
    THEN '(' || character_maximum_length || ')' ELSE '' END ||
    CASE WHEN is_nullable = 'NO' THEN ' NOT NULL' ELSE '' END, 
    ', ') || ');'
FROM 
    information_schema.columns 
WHERE 
    table_name = 'your_table'
GROUP BY 
    table_name;

For a more complete solution that includes constraints and indexes:

SELECT 
    'CREATE TABLE ' || n.nspname || '.' || c.relname || E'\n(\n' ||
    array_to_string(
        array_agg(
            '    ' || a.attname || ' ' || 
            pg_catalog.format_type(a.atttypid, a.atttypmod) ||
            CASE 
                WHEN a.attnotnull THEN ' NOT NULL'
                ELSE ''
            END
        ),
        E',\n'
    ) || E'\n);\n' ||
    COALESCE(
        (SELECT 
            E'\nALTER TABLE ' || n.nspname || '.' || c.relname || 
            E' ADD CONSTRAINT ' || conname || ' ' || 
            pg_get_constraintdef(oid) || E';\n'
         FROM 
            pg_constraint
         WHERE 
            conrelid = c.oid AND 
            contype IN ('p','f','u') AND
            connamespace = n.oid
         ORDER BY 
            contype DESC
        ),
        ''
    ) || 
    COALESCE(
        (SELECT 
            string_agg(
                E'\nCREATE INDEX ' || i.relname || ' ON ' || 
                n.nspname || '.' || c.relname || ' ' || 
                pg_get_indexdef(indexrelid) || E';\n',
                ''
            )
         FROM 
            pg_index x
         JOIN 
            pg_class i ON i.oid = x.indexrelid
         WHERE 
            x.indrelid = c.oid AND 
            i.relnamespace = n.oid
        ),
        ''
    ) AS table_definition
FROM 
    pg_class c
JOIN 
    pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN 
    pg_attribute a ON a.attrelid = c.oid AND a.attnum > 0
WHERE 
    n.nspname = 'your_schema' AND 
    c.relname = 'your_table' AND 
    NOT a.attisdropped
GROUP BY 
    n.nspname, c.relname, c.oid;

When working with WCF or other remote access methods, you might want to wrap this in a function:

CREATE OR REPLACE FUNCTION get_table_definition(p_schema text, p_table text)
RETURNS text AS $$
DECLARE
    v_result text;
BEGIN
    -- Implementation using the query above
    -- ...
    RETURN v_result;
END;
$$ LANGUAGE plpgsql;

Then call it remotely through your WCF service to get the complete table definition.