하위 쿼리를 사용하여 postgres에서 테이블 행 업데이트


301

postgres 8.4를 사용하여 목표는 기존 테이블을 업데이트하는 것입니다.

CREATE TABLE public.dummy
(
  address_id SERIAL,
  addr1 character(40),
  addr2 character(40),
  city character(25),
  state character(2),
  zip character(5),
  customer boolean,
  supplier boolean,
  partner boolean

)
WITH (
  OIDS=FALSE
);

처음에는 insert 문을 사용하여 쿼리를 테스트했습니다.

insert into address customer,supplier,partner
SELECT  
    case when cust.addr1 is not null then TRUE else FALSE end customer, 
    case when suppl.addr1 is not null then TRUE else FALSE end supplier,
    case when partn.addr1 is not null then TRUE else FALSE end partner
from (
    SELECT *
        from address) pa
    left outer join cust_original cust
        on (pa.addr1=cust.addr1 and pa.addr2=cust.addr2 and pa.city=cust.city 
            and pa.state=cust.state and substring(cust.zip,1,5) = pa.zip  )
    left outer join supp_original suppl 
        on (pa.addr1=suppl.addr1 and pa.addr2=suppl.addr2 and pa.city=suppl.city 
                and pa.state=suppl.state and pa.zip = substring(suppl.zip,1,5))
    left outer join partner_original partn
        on (pa.addr1=partn.addr1 and pa.addr2=partn.addr2 and pa.city=partn.city
                  and pa.state=partn.state and pa.zip = substring(partn.zip,1,5) )
where pa.address_id = address_id

초보자이기 때문에 업데이트 문으로 변환하는 데 실패했습니다. 즉, select 문에서 반환 된 값으로 기존 행을 업데이트합니다. 도움을 주시면 감사하겠습니다.


주소 테이블에 행이 존재하는지 확인하는 데 사용할 수있는 모든 종류의 ID가 있습니까?
Andrey Adamovich

예,하지만 시스템은 생성됩니다.
stackover

답변:


681

Postgres는 다음을 허용합니다.

UPDATE dummy
SET customer=subquery.customer,
    address=subquery.address,
    partn=subquery.partn
FROM (SELECT address_id, customer, address, partn
      FROM  /* big hairy SQL */ ...) AS subquery
WHERE dummy.address_id=subquery.address_id;

이 구문은 표준 SQL이 아니지만 표준 SQL보다이 유형의 쿼리에 훨씬 편리합니다. 나는 오라클이 적어도 비슷한 것을 받아들이라고 믿는다.


예를 들어 조금 다른 것을 시도하고있는 것 같습니다. 3 개의 부울 열 c1, c2, c3이 있으면 모두 처음에 false로 설정됩니다. 그러나 하위 쿼리를 기반으로 true로 설정되어 있습니다. (subquery1)의 id 인 경우 c1 = TRUE를 설정하고, (subquery2)의 id 인 c2 = TRUE를 설정하고, (subquery3)의 id 인 c3 = True를 설정하십시오. 이 업데이트를 3 업데이트로 나눌 때 성공했지만 단일 업데이트로 결과를 얻는 방법을 잘 모르겠습니다. 이것이 의미가 있기를 바랍니다.
Stackover

3
FWIW에서 Oracle은 기본 구성을 허용하지만 테이블이 커질수록 업데이트 성능이 크게 저하되는 경향이 있습니다. 오라클도 MERGE 문을 지원하기 때문에 괜찮습니다.
gsiems

3
이것은 완전히 PostgreSQL의 9.5에서 작동하지 않습니다, 나는 얻을ERROR: 42P01: relation "dummy" does not exist
user9645

72
dummy업데이트하려는 테이블 이름으로 바꿔야합니다. 신청하기 전에 질문과 답변을 이해하십시오.
Andrew Lazarus

1
쿼리의 시작 부분에서 왼쪽 열의 경로를 지정할 필요가 없으며 끝 부분 만 지정할 필요가 없습니다. 그렇지 않으면 db가 ERROR로 불평합니다. 열 참조 "address_id"가 모호합니다
OJVM


51

조인을 사용하여 성능이 향상되지 않으면 가독성을 위해 CTE (Common Table Expressions)를 선호합니다.

WITH subquery AS (
    SELECT address_id, customer, address, partn
    FROM  /* big hairy SQL */ ...
)
UPDATE dummy
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE dummy.address_id = subquery.address_id;

좀 더 현대적인 IMHO.


1
이 구문은 v9.1 이전의 이전 버전의 Postgres와 호환되지 않습니다 ( postgresql.org/docs/9.1/static/sql-update.html 및 이전 버전 참조). 나는 v8.2에 있습니다. FROM 키워드 다음에 전체 CTE / With 문을 괄호 안에 넣으면 작동합니다.
Spcogg가 2

9

행을 업데이트하는 방법에는 여러 가지가 있습니다.

그것이 올 때 UPDATE하위 쿼리를 사용하여 행, 이러한 접근 방식 중 하나를 사용할 수 있습니다.

  1. 접근법 -1 [직접 테이블 참조 사용]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2>
WHERE
  <table1>.address_id=<table2>.address_i;

설명 : table1업데이트하려는 table2 테이블이고, 대체 / 업데이트 할 값을 얻을 수있는 테이블입니다. 의 데이터 FROM를 가져 오기 위해 절 을 사용 하고 table2있습니다. WHERE 절은 적절한 데이터 매핑을 설정하는 데 도움이됩니다.

  1. 접근 -2 [하위 쿼리 사용]
UPDATE
  <table1>
SET
  customer=subquery.customer,
  address=subquery.address,
  partn=subquery.partn
FROM
  (
    SELECT
      address_id, customer, address, partn
    FROM  /* big hairy SQL */ ...
  ) AS subquery
WHERE
  dummy.address_id=subquery.address_id;

설명 : 여기서 우리는 FROM절 안에서 서브 쿼리를 사용 하고 그에 별명을 부여합니다. 테이블처럼 작동합니다.

  1. 접근법 -3 [여러 조인 된 테이블 사용]
UPDATE
  <table1>
SET
  customer=<table2>.customer,
  address=<table2>.address,
  partn=<table2>.partn
FROM
  <table2> as t2
  JOIN <table3> as t3
  ON
    t2.id = t3.id
WHERE
  <table1>.address_id=<table2>.address_i;

설명 : 때때로 테이블 조인의 상황에 직면하여 업데이트에 대한 적절한 데이터를 얻는 것이 매우 중요합니다. 이를 위해 Postgres를 사용하면 FROM조항 내에서 여러 테이블을 조인 할 수 있습니다 .

  1. 접근법 -4 [With 문 사용]

    • 4.1 [단순 쿼리 사용]
WITH subquery AS (
    SELECT
      address_id,
      customer,
      address,
      partn
    FROM
      <table1>;
)
UPDATE <table-X>
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE <table-X>.address_id = subquery.address_id;
  • 4.2 [복잡한 JOIN으로 쿼리 사용]
WITH subquery AS (
    SELECT address_id, customer, address, partn
    FROM
      <table1> as t1
    JOIN
      <table2> as t2
    ON
      t1.id = t2.id;
    -- You can build as COMPLEX as this query as per your need.
)
UPDATE <table-X>
SET customer = subquery.customer,
    address  = subquery.address,
    partn    = subquery.partn
FROM subquery
WHERE <table-X>.address_id = subquery.address_id;

설명 : Postgres 9.1부터 this ( WITH) 개념이 도입되었습니다. 이를 사용하여 복잡한 쿼리를 수행하고 원하는 결과를 생성 할 수 있습니다. 여기서는이 방법을 사용하여 테이블을 업데이트합니다.

도움이 되길 바랍니다 .😊


1
update json_source_tabcol as d
set isnullable = a.is_Nullable
from information_schema.columns as a 
where a.table_name =d.table_name 
and a.table_schema = d.table_schema 
and a.column_name = d.column_name;

1

@Mayur "4.2 [복잡한에 사용 쿼리 가입] '공통 테이블 식 (CTE는) 나를 위해 트릭을했다.

WITH cte AS (
SELECT e.id, e.postcode
FROM employees e
LEFT JOIN locations lc ON lc.postcode=cte.postcode
WHERE e.id=1
)
UPDATE employee_location SET lat=lc.lat, longitude=lc.longi
FROM cte
WHERE employee_location.id=cte.id;

이것이 도움이되기를 바랍니다 ... : D

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