C'è un modo per copiare lo schema esistente e generare un nuovo schema con un altro nome nello stesso database in postgres.Copia schema e crea un nuovo schema con nome diverso nello stesso database
risposta
- Se per schema copia intendi copia un database, quindi basta usare
TEMPLATE
opzione per creare una copia:CREATE DATABASE dbname_target TEMPLATE dbname_source;
Questo copierà i dati troppo. Quindi potresti voler creare il tuo modello se hai bisogno di molte copie. Vedi Template Databases.
- Se è necessario solo schema, allora vi suggerisco di mettere i vostri script DB DDL sotto controllo del codice sorgente (che è una buona idea in ogni modo) e hanno uno script separato (su modelli) che creerà lo schema per voi . Fondamentalmente si dispone di un file SQL, in cui si sostituisce un
${schema_name}
con il nuovo nome dello schema e quindi si esegue questo script sul database. In questo modo, se apporti una modifica a questoschema
, puoi anche disporre di script per aggiornare lo schema in una nuova versione, che in questo caso dovrai eseguire per ogni schema utente.
Utilizzare pg_dump per scaricare lo schema corrente in un file formato SQL. Aprire il file, sostituire lo schemaname con il nuovo nome ed eseguire questo script nel database per creare il nuovo schema e tutti gli altri oggetti all'interno di questo schema.
Ho un problema: se si sostituisce 'oldschema' con' newschema' nel file sql scaricato, non sembra esserci un modo definitivo per cambiare solo il testo in quel file che è riferendosi allo schema, giusto? Ad esempio, se ho uno schema con una parola comune come "ciao", allora tutte le istanze di hello (anche le relative istanze non correlate allo schema) saranno sostituite? –
Ho eseguito alcuni test e ho trovato che il risultato fa riferimento allo schema di origine. Quindi, ecco la mia versione migliorata:
-- Function: clone_schema(source text, dest text, include_records boolean default true, show_details boolean default false)
-- DROP FUNCTION clone_schema(text, text, boolean, boolean);
CREATE OR REPLACE FUNCTION clone_schema(
source_schema text,
dest_schema text,
include_recs boolean DEFAULT true,
show_details boolean DEFAULT false)
RETURNS void AS
$BODY$
-- This function will clone all sequences, tables, data, views & functions from any existing schema to a new one
-- SAMPLE CALL:
-- SELECT clone_schema('public', 'new_schema');
-- SELECT clone_schema('public', 'new_schema', TRUE);
-- SELECT clone_schema('public', 'new_schema', TRUE, TRUE);
DECLARE
src_oid oid;
tbl_oid oid;
func_oid oid;
object text;
buffer text;
srctbl text;
default_ text;
column_ text;
qry text;
xrec record;
dest_qry text;
v_def text;
seqval bigint;
sq_last_value bigint;
sq_max_value bigint;
sq_start_value bigint;
sq_increment_by bigint;
sq_min_value bigint;
sq_cache_value bigint;
sq_log_cnt bigint;
sq_is_called boolean;
sq_is_cycled boolean;
sq_cycled char(10);
rec record;
source_schema_dot text = source_schema || '.';
dest_schema_dot text = dest_schema || '.';
BEGIN
-- Check that source_schema exists
SELECT oid INTO src_oid
FROM pg_namespace
WHERE nspname = quote_ident(source_schema);
IF NOT FOUND
THEN
RAISE NOTICE 'source schema % does not exist!', source_schema;
RETURN ;
END IF;
-- Check that dest_schema does not yet exist
PERFORM nspname
FROM pg_namespace
WHERE nspname = quote_ident(dest_schema);
IF FOUND
THEN
RAISE NOTICE 'dest schema % already exists!', dest_schema;
RETURN ;
END IF;
EXECUTE 'CREATE SCHEMA ' || quote_ident(dest_schema) ;
-- Defaults search_path to destination schema
PERFORM set_config('search_path', dest_schema, true);
-- Create sequences
-- TODO: Find a way to make this sequence's owner is the correct table.
FOR object IN
SELECT sequence_name::text
FROM information_schema.sequences
WHERE sequence_schema = quote_ident(source_schema)
LOOP
EXECUTE 'CREATE SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object);
srctbl := quote_ident(source_schema) || '.' || quote_ident(object);
EXECUTE 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called
FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';'
INTO sq_last_value, sq_max_value, sq_start_value, sq_increment_by, sq_min_value, sq_cache_value, sq_log_cnt, sq_is_cycled, sq_is_called ;
IF sq_is_cycled
THEN
sq_cycled := 'CYCLE';
ELSE
sq_cycled := 'NO CYCLE';
END IF;
EXECUTE 'ALTER SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object)
|| ' INCREMENT BY ' || sq_increment_by
|| ' MINVALUE ' || sq_min_value
|| ' MAXVALUE ' || sq_max_value
|| ' START WITH ' || sq_start_value
|| ' RESTART ' || sq_min_value
|| ' CACHE ' || sq_cache_value
|| sq_cycled || ' ;' ;
buffer := quote_ident(dest_schema) || '.' || quote_ident(object);
IF include_recs
THEN
EXECUTE 'SELECT setval(''' || buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ;
ELSE
EXECUTE 'SELECT setval(''' || buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ;
END IF;
IF show_details THEN RAISE NOTICE 'Sequence created: %', object; END IF;
END LOOP;
-- Create tables
FOR object IN
SELECT TABLE_NAME::text
FROM information_schema.tables
WHERE table_schema = quote_ident(source_schema)
AND table_type = 'BASE TABLE'
LOOP
buffer := dest_schema || '.' || quote_ident(object);
EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE ' || quote_ident(source_schema) || '.' || quote_ident(object)
|| ' INCLUDING ALL)';
IF include_recs
THEN
-- Insert records from source table
EXECUTE 'INSERT INTO ' || buffer || ' SELECT * FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';';
END IF;
FOR column_, default_ IN
SELECT column_name::text,
REPLACE(column_default::text, source_schema, dest_schema)
FROM information_schema.COLUMNS
WHERE table_schema = dest_schema
AND TABLE_NAME = object
AND column_default LIKE 'nextval(%' || quote_ident(source_schema) || '%::regclass)'
LOOP
EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_;
END LOOP;
IF show_details THEN RAISE NOTICE 'base table created: %', object; END IF;
END LOOP;
-- add FK constraint
FOR xrec IN
SELECT ct.conname as fk_name, rn.relname as tb_name, 'ALTER TABLE ' || quote_ident(dest_schema) || '.' || quote_ident(rn.relname)
|| ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || replace(pg_get_constraintdef(ct.oid), source_schema_dot, '') || ';' as qry
FROM pg_constraint ct
JOIN pg_class rn ON rn.oid = ct.conrelid
WHERE connamespace = src_oid
AND rn.relkind = 'r'
AND ct.contype = 'f'
LOOP
IF show_details THEN RAISE NOTICE 'Creating FK constraint %.%...', xrec.tb_name, xrec.fk_name; END IF;
--RAISE NOTICE 'DEF: %', xrec.qry;
EXECUTE xrec.qry;
END LOOP;
-- Create functions
FOR xrec IN
SELECT proname as func_name, oid as func_oid
FROM pg_proc
WHERE pronamespace = src_oid
LOOP
IF show_details THEN RAISE NOTICE 'Creating function %...', xrec.func_name; END IF;
SELECT pg_get_functiondef(xrec.func_oid) INTO qry;
SELECT replace(qry, source_schema_dot, '') INTO dest_qry;
EXECUTE dest_qry;
END LOOP;
-- add Table Triggers
FOR rec IN
SELECT
trg.tgname AS trigger_name,
tbl.relname AS trigger_table,
CASE
WHEN trg.tgenabled='O' THEN 'ENABLED'
ELSE 'DISABLED'
END AS status,
CASE trg.tgtype::integer & 1
WHEN 1 THEN 'ROW'::text
ELSE 'STATEMENT'::text
END AS trigger_level,
CASE trg.tgtype::integer & 66
WHEN 2 THEN 'BEFORE'
WHEN 64 THEN 'INSTEAD OF'
ELSE 'AFTER'
END AS action_timing,
CASE trg.tgtype::integer & cast(60 AS int2)
WHEN 16 THEN 'UPDATE'
WHEN 8 THEN 'DELETE'
WHEN 4 THEN 'INSERT'
WHEN 20 THEN 'INSERT OR UPDATE'
WHEN 28 THEN 'INSERT OR UPDATE OR DELETE'
WHEN 24 THEN 'UPDATE OR DELETE'
WHEN 12 THEN 'INSERT OR DELETE'
WHEN 32 THEN 'TRUNCATE'
END AS trigger_event,
'EXECUTE PROCEDURE ' || (SELECT nspname FROM pg_namespace where oid = pc.pronamespace)
|| '.' || proname || '('
|| regexp_replace(replace(trim(trailing '\000' from encode(tgargs,'escape')), '\000',','),'{(.+)}','''{\1}''','g')
|| ')' as action_statement
FROM pg_trigger trg
JOIN pg_class tbl on trg.tgrelid = tbl.oid
JOIN pg_proc pc ON pc.oid = trg.tgfoid
WHERE trg.tgname not like 'RI_ConstraintTrigger%'
AND trg.tgname not like 'pg_sync_pg%'
AND tbl.relnamespace = (SELECT oid FROM pg_namespace where nspname = quote_ident(source_schema))
LOOP
buffer := dest_schema || '.' || quote_ident(rec.trigger_table);
IF show_details THEN RAISE NOTICE 'Creating trigger % % % ON %...', rec.trigger_name, rec.action_timing, rec.trigger_event, rec.trigger_table; END IF;
EXECUTE 'CREATE TRIGGER ' || rec.trigger_name || ' ' || rec.action_timing
|| ' ' || rec.trigger_event || ' ON ' || buffer || ' FOR EACH '
|| rec.trigger_level || ' ' || replace(rec.action_statement, source_schema_dot, '');
END LOOP;
-- Create views
FOR object IN
SELECT table_name::text,
view_definition
FROM information_schema.views
WHERE table_schema = quote_ident(source_schema)
LOOP
buffer := dest_schema || '.' || quote_ident(object);
SELECT replace(view_definition, source_schema_dot, '') INTO v_def
FROM information_schema.views
WHERE table_schema = quote_ident(source_schema)
AND table_name = quote_ident(object);
IF show_details THEN RAISE NOTICE 'Creating view % AS %', object, regexp_replace(v_def, '[\n\r]+', ' ', 'g'); END IF;
EXECUTE 'CREATE OR REPLACE VIEW ' || buffer || ' AS ' || v_def || ';' ;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Questa sembra essere la soluzione migliore che ho trovato.
L'idea è di utilizzare pg_dump con le opzioni -O (nessun proprietario) e -o (oid) per ottenere l'output di testo normale senza lo schema di origine e le informazioni sul proprietario..
Tale uscita a filtrare attraverso sed sostituendo la voce predefinita
SET search_path = source_schema, pg_catalog;
con comando per creare il nuovo schema e impostare il percorso di ricerca predefinito ad esso
CREATE SCHEMA new_schema;
SET search_path = new_schema, pg_catalog;
Dopo che ho reindirizzare la stream to psql registrazione per utente desiderato e database a cui verrà copiata la copia dello schema.
Il comando finale per copiare lo schema 'pubblico' a schema '2016' nello stesso database 'B1' si presenta così:
pg_dump -U postgres -Oo -n public -d b1 | sed 's/SET search_path = public, pg_catalog;/CREATE SCHEMA "2016";SET search_path = "2016", pg_catalog;/' | psql -U postgres -d b1
Si prega di notare che le sovvenzioni non siano trasferiti dallo schema di origine al nuovo uno.
Check out this Pagina wiki di PostgreSQL. Contiene una funzione per clone_schema
come richiesto, ma questa funzione clona solo le tabelle. La pagina si riferisce al post this, che contiene una funzione che clona tutto ciò che è necessario per lo schema.Questa funzione ha funzionato bene per me, sono riuscito ad eseguirla con l'API JDBC.
Ma ho avuto alcuni problemi quando i nomi degli schemi contenevano -
o lettere maiuscole. Dopo una ricerca ho scoperto che la fonte del problema è il metodo quote_ident()
. Modifico la funzione clone_schema
per funzionare con qualsiasi nome di schema. Condivido la nuova funzione qui, spero che vi aiuterà qualcuno:
-- Function: clone_schema(text, text)
-- DROP FUNCTION clone_schema(text, text);
CREATE OR REPLACE FUNCTION clone_schema(
source_schema text,
dest_schema text,
include_recs boolean)
RETURNS void AS
$BODY$
-- This function will clone all sequences, tables, data, views & functions from any existing schema to a new one
-- SAMPLE CALL:
-- SELECT clone_schema('public', 'new_schema', TRUE);
DECLARE
src_oid oid;
tbl_oid oid;
func_oid oid;
object text;
buffer text;
srctbl text;
default_ text;
column_ text;
qry text;
dest_qry text;
v_def text;
seqval bigint;
sq_last_value bigint;
sq_max_value bigint;
sq_start_value bigint;
sq_increment_by bigint;
sq_min_value bigint;
sq_cache_value bigint;
sq_log_cnt bigint;
sq_is_called boolean;
sq_is_cycled boolean;
sq_cycled char(10);
BEGIN
-- Check that source_schema exists
SELECT oid INTO src_oid
FROM pg_namespace
WHERE nspname = source_schema;
IF NOT FOUND
THEN
RAISE EXCEPTION 'source schema % does not exist!', source_schema;
RETURN ;
END IF;
-- Check that dest_schema does not yet exist
PERFORM nspname
FROM pg_namespace
WHERE nspname = dest_schema;
IF FOUND
THEN
RAISE EXCEPTION 'dest schema % already exists!', dest_schema;
RETURN ;
END IF;
EXECUTE 'CREATE SCHEMA "' || dest_schema || '"';
-- Create sequences
-- TODO: Find a way to make this sequence's owner is the correct table.
FOR object IN
SELECT sequence_name::text
FROM information_schema.sequences
WHERE sequence_schema = source_schema
LOOP
EXECUTE 'CREATE SEQUENCE "' || dest_schema || '".' || quote_ident(object);
srctbl := '"' || source_schema || '".' || quote_ident(object);
EXECUTE 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called
FROM "' || source_schema || '".' || quote_ident(object) || ';'
INTO sq_last_value, sq_max_value, sq_start_value, sq_increment_by, sq_min_value, sq_cache_value, sq_log_cnt, sq_is_cycled, sq_is_called ;
IF sq_is_cycled
THEN
sq_cycled := 'CYCLE';
ELSE
sq_cycled := 'NO CYCLE';
END IF;
EXECUTE 'ALTER SEQUENCE ' || dest_schema || '.' || quote_ident(object)
|| ' INCREMENT BY ' || sq_increment_by
|| ' MINVALUE ' || sq_min_value
|| ' MAXVALUE ' || sq_max_value
|| ' START WITH ' || sq_start_value
|| ' RESTART ' || sq_min_value
|| ' CACHE ' || sq_cache_value
|| sq_cycled || ' ;' ;
buffer := '"' || dest_schema || '".' || quote_ident(object);
IF include_recs
THEN
EXECUTE 'SELECT setval(''' || buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ;
ELSE
EXECUTE 'SELECT setval(''' || buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ;
END IF;
END LOOP;
-- Create tables
FOR object IN
SELECT TABLE_NAME::text
FROM information_schema.tables
WHERE table_schema = source_schema
AND table_type = 'BASE TABLE'
LOOP
buffer := dest_schema || '.' || quote_ident(object);
EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE "' || source_schema || '".' || quote_ident(object)
|| ' INCLUDING ALL)';
IF include_recs
THEN
-- Insert records from source table
EXECUTE 'INSERT INTO ' || buffer || ' SELECT * FROM "' || source_schema || '".' || quote_ident(object) || ';';
END IF;
FOR column_, default_ IN
SELECT column_name::text,
REPLACE(column_default::text, source_schema, dest_schema)
FROM information_schema.COLUMNS
WHERE table_schema = dest_schema
AND TABLE_NAME = object
AND column_default LIKE 'nextval(%' || source_schema || '%::regclass)'
LOOP
EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_;
END LOOP;
END LOOP;
-- add FK constraint
FOR qry IN
SELECT 'ALTER TABLE "' || dest_schema || '".' || quote_ident(rn.relname)
|| ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || pg_get_constraintdef(ct.oid) || ';'
FROM pg_constraint ct
JOIN pg_class rn ON rn.oid = ct.conrelid
WHERE connamespace = src_oid
AND rn.relkind = 'r'
AND ct.contype = 'f'
LOOP
EXECUTE qry;
END LOOP;
-- Create views
FOR object IN
SELECT table_name::text,
view_definition
FROM information_schema.views
WHERE table_schema = source_schema
LOOP
buffer := dest_schema || '.' || quote_ident(object);
SELECT view_definition INTO v_def
FROM information_schema.views
WHERE table_schema = source_schema
AND table_name = quote_ident(object);
EXECUTE 'CREATE OR REPLACE VIEW ' || buffer || ' AS ' || v_def || ';' ;
END LOOP;
-- Create functions
FOR func_oid IN
SELECT oid
FROM pg_proc
WHERE pronamespace = src_oid
LOOP
SELECT pg_get_functiondef(func_oid) INTO qry;
SELECT replace(qry, source_schema, dest_schema) INTO dest_qry;
EXECUTE dest_qry;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION clone_schema(text, text, boolean)
OWNER TO postgres;
- 1. Oracle stesso nome tabella su schema diverso?
- 2. Posizione database nello schema
- 3. Diversi tipi di ereditarietà nello stesso schema
- 4. Copia tutto il contenuto del database (schema e dati)
- 5. git crea un nuovo ramo con lo stesso nome, verrà inserito nello stesso telecomando?
- 6. Database locale con schema
- 7. Semplifica Database ER Schema/Schema
- 8. Corrispondenza dell'array secondario nell'array. Schema nello schema
- 9. Programmazione grafica nello schema
- 10. Come si crea una tabella SQL con uno schema diverso?
- 11. Codice EF, come registrare lo stesso nome di tabella con uno schema diverso?
- 12. Leggi macro nello schema
- 13. Crea sequenza in migrazione non riflessa nello schema
- 14. Migrazione graduale a un nuovo schema di database. ¿Suggerimenti?
- 15. Schema del database EtherPad?
- 16. Aggiunta di un elemento all'Elenco nello schema
- 17. Concedere "crea schema" sul database a un utente?
- 18. Come creare una copia dello schema completo sullo stesso database in Oracle
- 19. car e cdr nello Schema me crazy
- 20. Argomenti e punti facoltativi nello schema
- 21. Differenza tra eq? e = nello schema?
- 22. Esiste uno strumento opensource per convertire lo schema xml nello schema del database per linux?
- 23. Schema server SQL e schema predefinito
- 24. MySQL Workbench - Lo schema è lo stesso del database?
- 25. Continuazione (chiamata/cc) nello schema
- 26. Informazioni su "cond" nello schema
- 27. implementare l'esecuzione parallela nello schema
- 28. Recupera schema database
- 29. Carica dati nello schema dei dati principali
- 30. Come elencare le relazioni nello schema postgres
Forse questo aiuterà http://stackoverflow.com/q/12572088/1695418 – icebreaker