호출 예시

CALL LINE_UP_SERIAL_COLUMN('테이블명', '컬럼명')
CALL LINE_UP_SERIAL_COLUMN('스키마명.테이블명', '컬럼명')

정의

--------------------------------------------------------------------------------------------
-- Serial 컬럼 빈 값 채워서 줄세우기
--------------------------------------------------------------------------------------------
-- [예제]
-- CALL LINE_UP_SERIAL_COLUMN('스키마명.테이블명', '컬럼명');
-- CALL LINE_UP_SERIAL_COLUMN('테이블명', '컬럼명'); -- public 테이블
--------------------------------------------------------------------------------------------
DROP PROCEDURE IF EXISTS LINE_UP_SERIAL_COLUMN;
        CREATE PROCEDURE LINE_UP_SERIAL_COLUMN
(
    _schema_table_name text,
    _column_only_name text
)
AS $$
DECLARE 
    _dot_pos int;
    _sequence_name text;
    _schema_only_name text;
    _table_only_name text;
    _next_seq_value int;
BEGIN
    _dot_pos := strpos(_schema_table_name, '.');
    
    -- 스키마명, 테이블명
    IF _dot_pos = 0 THEN
        _schema_only_name := 'public';
        _table_only_name := _schema_table_name;
        _schema_table_name := _schema_only_name || '.' || _table_only_name;
    ELSE
        _schema_only_name := substring(_schema_table_name, 0, _dot_pos);
        _table_only_name := substring(_schema_table_name, _dot_pos + 1);
    END IF;
    
    -- 시퀀스명
    SELECT (REGEXP_MATCH(column_default, '''(.+)'''))[1] AS seq
    FROM information_schema.columns
    WHERE table_schema = _schema_only_name
      AND table_name = _table_only_name
      AND column_name = _column_only_name
      AND column_default LIKE 'nextval(%'
    INTO _sequence_name;
    
    -- [1] Serial 컬럼 MAX() 값 이후로 줄세우기 (PK값 중복 방지)
    EXECUTE FORMAT('
WITH cte AS (
    SELECT ROW_NUMBER() OVER (ORDER BY %2$s ASC) + MAX(%2$s) OVER () AS next_serial, ctid 
    FROM %1$s
)
UPDATE %1$s
   SET %2$s = cte.next_serial
  FROM cte
 WHERE %1$s.ctid = cte.ctid;
   ', _schema_table_name, _column_only_name);
    
    -- [2] Serial 컬럼 제대로 줄세우기
    EXECUTE FORMAT('
WITH cte AS (
    SELECT ROW_NUMBER() OVER (ORDER BY %2$s ASC) AS next_serial, ctid 
    FROM %1$s
)
UPDATE %1$s
   SET %2$s = cte.next_serial
  FROM cte
 WHERE %1$s.ctid = cte.ctid;
   ', _schema_table_name, _column_only_name);
   
   -- 다음 Sequence 값 생성
   EXECUTE 'SELECT MAX('||_column_only_name||') FROM '||_schema_table_name INTO _next_seq_value;
   
   -- Sequence 값 설정
   EXECUTE 'SELECT setval(' || quote_literal(_sequence_name) || ', ' || _next_seq_value || ', true)';
   -- EXECUTE FORMAT('ALTER SEQUENCE %s RESTART WITH %s', _sequence_name, _next_seq_value);
   
   RAISE NOTICE 'TABLE : [%]', _schema_table_name;
   RAISE NOTICE 'COLUMN: [%]', _column_only_name;
   RAISE NOTICE 'MAX VALUE: [%]', _next_seq_value;
    
END; $$
LANGUAGE plpgsql;