0

我正在尝试使用Copy schema 中的函数复制数据库架构,并在同一数据库中创建具有不同名称的新架构

-- 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;
  table_rec        record;
  seq_rec          record;
  object           text;
  sequence_        text;
  table_           text;
  buffer           text;
  seq_buffer       text;
  table_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 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;

  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 sequences
  FOR seq_rec IN
    SELECT
      s.sequence_name::text,
      table_name,
      column_name
    FROM information_schema.sequences s
    JOIN (
      SELECT
        substring(column_default from E'^nextval\\(''(?:[^"'']?.*["'']?\\.)?([^'']*)''(?:::text|::regclass)?\\)')::text as seq_name,
        table_name,
        column_name
      FROM information_schema.columns
      WHERE column_default LIKE 'nextval%'
        AND table_schema = source_schema
    ) c ON c.seq_name = s.sequence_name
    WHERE sequence_schema = source_schema
  LOOP
    seq_buffer := quote_ident(dest_schema) || '.' || quote_ident(seq_rec.sequence_name);

    EXECUTE 'CREATE SEQUENCE ' || seq_buffer || ';';

    qry := 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called
              FROM "' || source_schema || '".' || quote_ident(seq_rec.sequence_name) || ';';
    EXECUTE qry 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 '   || seq_buffer
            || ' 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
            || ' OWNED BY '     || quote_ident(dest_schema ) || '.'
                                || quote_ident(seq_rec.table_name) || '.'
                                || quote_ident(seq_rec.column_name) || ' '
            || sq_cycled || ' ;' ;

    IF include_recs
        THEN
            EXECUTE 'SELECT setval( ''' || seq_buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ;
    ELSE
            EXECUTE 'SELECT setval( ''' || seq_buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ;
    END IF;

    table_buffer := quote_ident(dest_schema) || '.' || quote_ident(seq_rec.table_name);

    FOR table_rec IN
      SELECT column_name::text AS column_,
             REPLACE(column_default::text, source_schema, quote_ident(dest_schema)) AS default_
        FROM information_schema.COLUMNS
       WHERE table_schema = dest_schema
         AND TABLE_NAME = seq_rec.table_name
         AND column_default LIKE 'nextval(%' || seq_rec.sequence_name || '%::regclass)'
    LOOP
      EXECUTE 'ALTER TABLE ' || table_buffer || ' ALTER COLUMN ' || table_rec.column_ || ' SET DEFAULT nextval(' || quote_literal(seq_buffer) || '::regclass);';
    END LOOP;

  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;

但是,当我尝试执行此操作时,出现错误:

错误:列“max_value”不存在也许您的意思是引用列“dict_test_value_seq.last_value”

当我试图获得该序列的 max_value 时,我得到了正确的结果。如何改进此功能以获取序列值?

4

1 回答 1

0

您正在使用 10 或更高版本的 PostgreSQL,这意味着您无法再通过从序列中选择来获取 max_value。相反,您需要访问pg_sequence目录,但您可能希望仅使用information_schema.sequences视图来简化查询:

SELECT start_value, minimum_value, maximum_value, increment, cycle_option
FROM information_schema.sequences
WHERE (sequence_schema, sequence_name) = ('schemaname','mysequence');
于 2021-07-27T09:20:26.527 回答