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.