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.