카테고리 없음

[씨#] SQL에서 기본 키로 행을 복제 하시겠습니까?

행복을전해요 2020. 12. 29. 22:32

PostgreSQL에 대해 잘 모르겠지만 대부분의 시스템과 같이 자동 증가를 지원하는 경우 기본 키 필드를 비워 둡니다. 그러나 이것은 열 이름을 지정해야 함을 의미합니다.

또한 clone이라고 말하면 레코드의 복제본을 원하는 것처럼 들리지만 설명에서 address1 및 address2 열은 동일한 데이터 행에 있습니다.

address1을 address2 열에 복제하려면 간단한 update 문을 사용할 수 있습니다.

정확히 동일한 두 개의 레코드를 갖도록 전체 행을 복제하려는 경우 이와 같은 것을 사용할 수 있으며 두 환경 모두에서 작동해야합니다.

INSERT INTO Addresses
( address1, address2 )
SELECT address1, address2
  FROM Addresses
   WHERE addressId = ID
   

이제 다음 질문은 한 DB 유형에서 다른 DB 유형으로 복제하고 있습니까? 그렇다면 어쨌든 앱으로 가져와야합니다. 그렇다면 nHibernate와 같은 것을 사용하여 db 레이어를 추상화하지 않는 이유는 무엇입니까?

목표가 복사본을 만드는 것이라면 위의 SQL을 사용하여 db에서 바로 수행 할 수 있습니다.

이 SQL이 아마도 가장 쉬울 수 있지만 (필요한 경우 시스템 / 마스터 테이블을 사용하여 db에서 반영 할 수 있음) 열 이름을 지정해야합니다. 주된 이유는 * 와일드 카드를 추가하자마자 원래 기본 키 열을 선택 목록에 포함 시키려고 시도하는 것입니다. 그러면 현재 가지고있는 열에 1 개의 추가 열이 있습니다.

삽입 문에서 와일드 카드를 사용할 때 알아야 할 또 다른 문제는 열 순서가 일치 해야한다는 것입니다 . 그렇지 않으면 예상치 못한 결과를 얻을 수 있습니다.

-------------------

Oracle과 마찬가지로 Postgres는 시퀀스를 사용하여 인공 / 대리 키에 대한 시퀀스 숫자 값을 생성합니다. 다음 값을 얻으려면 다음을 사용해야합니다.

NEXTVAL(your_sequence_name) 

... 기본 키에 대한 값을 설정하기 위해 INSERT 문에서. 이상한 이유로 열이 널 입력 가능하지 않는 한 INSERT 문에서 생략 할 수 없습니다. 따라서 Postgres에서는 다음을 사용해야합니다.

INSERT INTO PrimKeys 
SELECT NEXTVAL(your_sequence_name),
       [rest of columns, because you can't include the pk col/value]
         FROM PrimKeys 
          WHERE PrimKey='PrimKey1'
          

동등한 SQL Server 기능

SQL Server (및 MySQL)를 사용하면 열을 지정하지 않거나 NULL기본 키 열의 자리 표시 자로 제공하여 값을 제공 할 수 있습니다. 그것은 당신이 얻는 것만 큼 가깝습니다.

참고:

  • Postgre 시퀀스
-------------------

파티에 조금 늦었지만이 기능은 사람들에게 도움이 될 수 있습니다.

결과에서 텍스트 값을 구분하는 집계 함수를 만듭니다. 쉼표 구분 기호는 열 목록을 가져 오는 데 사용됩니다.

CREATE OR REPLACE FUNCTION concat_delimited( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$
  SELECT $1 || (CASE WHEN $1 = '' THEN '' ELSE $3 END) || $2;
  $$
  LANGUAGE SQL STRICT IMMUTABLE;
  
  CREATE AGGREGATE delimited_list_of ( TEXT, TEXT ) (
    SFUNC = concat_delimited,
      STYPE = TEXT,
        INITCOND = ''
        );
        

레코드를 복제하는 기능 생성

 CREATE OR REPLACE FUNCTION  duplicate(_schema text,_tbl text, _id integer)
 RETURNS integer AS 
  $BODY$
   DECLARE cols text;
      sql  text;
         result integer;
          BEGIN
             SELECT into  cols  delimited_list_of(column_name, ',') 
                FROM   information_schema.columns 
                   WHERE  table_schema =  _schema  AND table_name = _tbl  AND  column_name != 'id';
                   
                      raise notice 'Cols: %', cols;
                         sql := 'insert into ' || quote_ident(_schema) || '.' || quote_ident(_tbl) || '('  
                                || cols ||  ') SELECT ' || cols || ' FROM ' || quote_ident(_schema) || '.' 
                                       || quote_ident(_tbl) || ' WHERE id = ' || _id || ' RETURNING id' ;
                                       
                                           raise notice 'Query: %', sql;
                                               EXECUTE sql  into result;
                                                   RETURN result;
                                                    END;
                                                     $BODY$
                                                        LANGUAGE  plpgsql VOLATILE  COST 100;
                                                        

거기에서 복제 할 레코드의 스키마 이름, 테이블 이름 및 ID를 전달하면 생성 된 레코드의 ID가 반환됩니다.

select  duplicate('_schema','test_tbl',500001);

필드 이름 ID를 기본 / 고유 필드 이름으로 변경해야합니다.



출처
https://stackoverflow.com/questions/2002779