postgresql : INSERT INTO… (SELECT *…)


125

표준 SQL인지 확실하지 않습니다.

 INSERT INTO tblA 
 (SELECT id, time 
    FROM tblB 
   WHERE time > 1000)  

내가 찾고있는 것은 : tblA와 tblB가 다른 DB 서버에 있다면 어떻게 될까요 ?

PostgreSql이 유틸리티를 제공하거나 사용에 도움이되는 기능이 있습니까? INSERT query with PGresult struct

내 말은 SELECT id, time FROM tblB ...를 반환합니다 PGresult*사용하여 PQexec. PQexecINSERT 명령을 실행하기 위해 다른 구조체에서이 구조체를 사용할 수 있습니까?

편집 :
가능하지 않은 경우 PQresult *에서 값을 추출하고 다음과 같은 여러 INSERT 문 구문을 만듭니다.

INSERT INTO films (code, title, did, date_prod, kind) VALUES
    ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
    ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy'); 

이것으로 준비된 성명서를 작성할 수 있습니까! :(


게시 한 INSERT 구문이 ANSI인지는 모르겠지만 널리 지원됩니다 (Oracle, MySQL, SQL Server, SQLite ...). 그러나 대괄호는 필요하지 않습니다.
— OMG Ponies

답변:


152

Henrik이 작성한 것처럼 dblink를 사용하여 원격 데이터베이스에 연결하고 결과를 가져올 수 있습니다. 예를 들면 :

psql dbtest
CREATE TABLE tblB (id serial, time integer);
INSERT INTO tblB (time) VALUES (5000), (2000);

psql postgres
CREATE TABLE tblA (id serial, time integer);

INSERT INTO tblA
    SELECT id, time 
    FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB')
    AS t(id integer, time integer)
    WHERE time > 1000;

TABLE tblA;
 id | time 
----+------
  1 | 5000
  2 | 2000
(2 rows)

PostgreSQL에는 레코드 의사 유형 (함수의 인수 또는 결과 유형에만 해당)이있어 다른 (알 수없는) 테이블에서 데이터를 쿼리 할 수 ​​있습니다.

편집하다:

원하는 경우 준비된 진술로 만들 수 있으며 잘 작동합니다.

PREPARE migrate_data (integer) AS
INSERT INTO tblA
    SELECT id, time
    FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB')
    AS t(id integer, time integer)
    WHERE time > $1;

EXECUTE migrate_data(1000);
-- DEALLOCATE migrate_data;

편집 (예, 다른) :

방금 수정 된 질문을 봤습니다 (중복으로 마감했거나 이와 매우 유사 함).

내 이해가 정확하다면 (postgres에는 tbla가 있고 dbtest에는 tblb가 있으며 위와 같이 로컬 삽입 으로 원격 선택이 아닌 로컬 선택으로 원격 삽입 을 원합니다 ) :

psql dbtest

SELECT dblink_exec
(
    'dbname=postgres',
    'INSERT INTO tbla
        SELECT id, time
        FROM dblink
        (
            ''dbname=dbtest'',
            ''SELECT id, time FROM tblb''
        )
        AS t(id integer, time integer)
        WHERE time > 1000;'
);

중첩 된 dblink가 마음에 들지 않지만 AFAIK dblink_exec 본문 에서 tblB를 참조 할 수 없습니다 . LIMIT를 사용하여 상위 20 개 행을 지정하지만 먼저 ORDER BY 절을 사용하여 정렬해야한다고 생각합니다.


1
응답 해 주셔서 감사합니다. 글쎄요, 한 가지 더 빠른 질문 ... INSERT INTO tblA SELECT id, time FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB') AS t(id integer, time integer) WHERE time > 1000; 이것에 대해 준비된 진술을 할 수 있습니까?
— Mayank

안녕하세요 @ grzegorz-szpetkowski,이 논리는 오류를 제공합니다. 오류 : 암호가 필요합니다. 상세 : 슈퍼 유저가 아닌 사용자는 연결 문자열에 암호를 제공해야합니다.
— Neel Darji

34

지정 열에 삽입하려는 경우 :

INSERT INTO table (time)
(SELECT time FROM 
    dblink('dbname=dbtest', 'SELECT time FROM tblB') AS t(time integer) 
    WHERE time > 1000
);

9

dblink 를 사용하여 다른 데이터베이스에서 확인되는 뷰를 만들 수 있습니다 . 이 데이터베이스는 다른 서버에있을 수 있습니다.


답장을 보내 주셔서 감사합니다. 그러나 INSERT INTO ... (SELECT FROM ...)dblink를 사용하여 어떻게 작동 하는지 알지 못했습니다 . 내가 필요한 것은 INSERT INTO ...다른 DB 서버에 대한 dblink 세션에서 실행되지만 (SELECT FROM ...)현재 세션에서 실행되는 것입니다.
— Mayank

dblink가 지원하는 뷰로 tblA를 정의하기 만하면됩니다. 따라서 삽입, 업데이트, 삭제는 다른 데이터베이스에서 수행됩니다. dblink는 읽기 전용이 아닙니다.
— Hendrik Brummermann

9

이 표기법 (처음 여기에서 보임 )도 유용 해 보입니다.

insert into postagem (
  resumopostagem,
  textopostagem,
  dtliberacaopostagem,
  idmediaimgpostagem,
  idcatolico,
  idminisermao,
  idtipopostagem
) select
  resumominisermao,
  textominisermao,
  diaminisermao,
  idmediaimgminisermao,
  idcatolico ,
  idminisermao,
  1
from
  minisermao    

2
이것은 테이블이 동일한 데이터베이스에있을 때만 작동합니다. 질문은 다른 데이터베이스 의 테이블에서 데이터를 복사 하는 것과 관련이 있습니다 .
— Nitin Nain


1

다음은 dblink.

B가 소스 데이터베이스를 나타내고 A가 대상 데이터베이스를 나타낸다고 가정합니다. 그런 다음

  1. 원본 DB에서 대상 DB로 테이블 복사 :

    pg_dump -t <source_table> <source_db> | psql <target_db>
  2. psql 프롬프트를 열고 target_db에 연결 한 다음 간단한 사용 insert:

    psql
    # \c <target_db>;
    # INSERT INTO <target_table>(id, x, y) SELECT id, x, y FROM <source_table>;
  3. 마지막 으로 target_table 에서 생성 한 source_table 사본을 삭제합니다 .

    # DROP TABLE <source_table>;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.