하위 쿼리를 사용하여 SQL을 삭제하는 방법


15

테이블에서 중복 레코드를 삭제하기 위해 개발자 중 한 명이 다음 코드를 추가했습니다.

DELETE  SubQuery

FROM
(
    SELECT  ID
            ,FK1
            ,FK2
            ,CreatedDateTime
            ,ROW_NUMBER() OVER(PARTITION BY FK1, FK2 ORDER BY CreatedDateTime) AS RowNumber

    FROM    Table
)
AS SubQuery

WHERE   RowNumber > 1

코드를 검토 할 때 코드가 작동하지 않는다고 가정했지만 테스트 환경 (SQL 2014)에서 테스트하면 코드가 작동하는 것으로 나타났습니다!

SQL은 하위 쿼리를 해결하고 레코드를 삭제하는 방법을 어떻게 알 수 table있습니까?

답변:


14

subquery코드에서 당신이이라고 파생 테이블 . 기본 테이블이 아니라 쿼리가 실행되는 동안 "존재하는"테이블입니다. 같이 보기 (도라고 볼 테이블 ) - 최근 버전에서 CTE는 또 다른, 4 방법 쿼리 안에 테이블을 "정의"- 그들은 여러 가지면에서 테이블과 유사하다. 당신은 select그들에게서 할 수 있고, 다른 테이블 에서 사용 from하거나 join다른 테이블 에 사용할 수 있습니다 (기본 또는 아닙니다!).

일부 DBMS에서 (모든 DBMS가 동일한 방식으로 구현 한 것은 아님) 이러한 테이블 / 뷰를 업데이트 할 수 있습니다. 우리는 또한 수 그리고 "갱신"수단 update, insert로 또는 delete그들로부터.

그러나 제한 사항이 있으며 이는 예상 된 것입니다. subquery가 2 (또는 17 개의 테이블)의 조인 인 경우를 상상해보십시오 . 그러면 무엇을 delete의미할까요? (어떤 테이블에서 행을 삭제해야합니까?) 업데이트 가능한 뷰는 매우 복잡한 문제 입니다. 관계 이론에 대한 잘 알려진 전문가 인 크리스 데이트 (Chris Date)가 쓴이 주제에 관한 최근의 (2012 년) 저서가있다 : 업데이트 및 관계 이론 .

파생 테이블 (또는 뷰)이 하나의 기본 테이블 (으로 ​​제한됨 WHERE) 만 있고 no와 같이 매우 간단한 쿼리 GROUP BY인 경우 파생 테이블의 모든 행이 기본 기본 테이블의 한 행에 해당하므로 easy * 업데이트, 삽입 또는 삭제

하위 쿼리 내부의 코드가 더 복잡한 경우 파생 된 테이블 / 뷰의 행을 기본 기본 테이블 중 하나의 행으로 추적 / 해결할 수 있는지 여부에 따라 달라집니다.

SQL Server의 경우 MSDN의 업데이트 가능한 뷰 단락에서 자세한 내용을 읽을 수 있습니다 CREATE VIEW.

업데이트 가능한 뷰

다음 조건이 충족되는 한 뷰를 통해 기본 테이블의 데이터를 수정할 수 있습니다.

  • 모든 포함하여 수정 UPDATE, INSERT그리고 DELETE단 하나 개의 기본 테이블에서 문, 반드시 참조 열.

  • 뷰에서 수정중인 열은 테이블 열의 기본 데이터를 직접 참조해야합니다. 다음과 같은 다른 방법으로는 열을 파생시킬 수 없습니다.

  • 집계 함수 : AVG, COUNT, SUM, MIN, MAX, GROUPING, STDEV, STDEVP, VAR,와 VARP.

  • 계산. 다른 열을 사용하는 식에서 열을 계산할 수 없습니다. 집합 연산자를 사용하여 형성되는 열을 UNION, UNION ALL, CROSSJOIN, EXCEPT, 및 INTERSECT 계산에 양 및도 갱신되지 않는다.

  • 열은 영향을받지 않습니다 수정하고 GROUP BY, HAVING또는 DISTINCT절.

  • TOP뷰의 select_statement에서 WITH CHECK OPTION절 과 함께 사용되지 않습니다 .

이전 제한 사항 FROM은 뷰 자체에 적용되는 것처럼 뷰 절의 하위 쿼리에 적용됩니다. 일반적으로 데이터베이스 엔진은보기 정의에서 하나의 기본 테이블로 수정 사항을 명확하게 추적 할 수 있어야합니다.


실제로 delete보다 쉽고 복잡하지 않습니다 update. SQL Server는 기본 키 또는 기본 테이블의 어떤 행을 삭제할지를 식별하는 다른 방법 만 필요합니다. 의 경우 update계산 열을 업데이트 할 수 없다는 추가 제한이 있습니다. 쿼리를 수정하여 업데이트를 시도 할 수 있습니다. 를 업데이트하면 CreatedDateTime정상적으로 작동하지만 계산 된 RowNumber열 을 업데이트하려고 하면 오류가 발생합니다. 그리고 insert우리는이없는 기본 테이블의 모든 열 값을 제공해야 할 것 같은 더 복잡한 DEFAULT제약 조건을.


4

쿼리 계획을 볼 때 쉽게 볼 수 있습니다. 귀하의 경우 계획에는 행 번호를 처리하기위한 추가 세그먼트 및 시퀀스 프로젝트 연산자 만 포함됩니다. 이 유형의 작업은 SQL Server가 실제로 기본 테이블을 확인할 수있는 경우에만 작동합니다.

서브 쿼리 및 CTE에서 삭제는 완벽하게 지원되며 특히 중복 제거에 매우 효율적입니다. 또한 이전 버전의 SQL Server에서 사용하는 것을 기억합니다.

오래된 블로그 게시물 에 더 있습니다.

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