WHERE 절에서 SELECT 문을 사용하여 SQL DELETE 문을 작성하는 방법은 무엇입니까?


81

데이터베이스 : Sybase Advantage 11

데이터를 정규화하기 위해이 SELECT진술 에서 얻은 결과를 삭제하려고 합니다.

SELECT tableA.entitynum
FROM tableA q
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%')
AND (u.FldFormat = 'Date')
;

이것은 DELETE내가 생각해 낸 진술입니다.

DELETE FROM tableA
WHERE (SELECT q.entitynum
FROM tableA q
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%')
AND (u.FldFormat = 'Date'))
;

이 문을 실행하려고하면 계속해서이 오류가 발생합니다.

ERROR IN SCRIPT: poQuery: Error 7200:  AQE Error:  State = S0000;   NativeError = 2124;
[iAnywhere Solutions][Advantage SQL Engine]Invalid operand for operator: = Boolean value
cannot be operated with non-Boolean value.

나는 또한이 진술을 시도했다 :

DELETE FROM tableA 
INNER JOIN tableB u on (u.qlabel = tableA.entityrole AND u.fieldnum = tableA.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR tableA.memotext NOT LIKE '%/%/%')
AND (u.FldFormat = 'Date')
;

결과 :

ERROR IN SCRIPT: poQuery: Error 7200:  AQE Error:  State = 42000;   NativeError = 2117;
[iAnywhere Solutions][Advantage SQL Engine] Unexpected token: INNER -- Expecting semicolon.
-- Location of error in the SQL statement is: 23 (line: 2 column: 1)

누군가가 적절한 데이터가 제거되는 DELETE 쿼리를 올바르게 구성하는 데 도움을 줄 수 있습니까?


최악의 시나리오-임시 테이블을 만들고 해당 임시 테이블에 SELECT하고 임시 테이블을 조인 한 다음 임시 테이블을 삭제합니까?
PP.

답변:


143

올바른 레코드를 삭제하려면 TableA에서 기본 키를 식별해야합니다. 기본 키는 단일 열이거나 테이블의 행을 고유하게 식별하는 여러 열의 조합 일 수 있습니다. 기본 키가 없으면 ROWID 의사 열을 기본 키로 사용할 수 있습니다.

DELETE FROM tableA
WHERE ROWID IN 
  ( SELECT q.ROWID
    FROM tableA q
      INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
    WHERE (LENGTH(q.memotext) NOT IN (8,9,10) OR q.memotext NOT LIKE '%/%/%')
      AND (u.FldFormat = 'Date'));

1
빠른 응답에 대해 Alex에게 감사드립니다. @AlexW 나는 당신이 머리에 못을 박았다고 생각합니다. 이 테이블이 작동하는 방식은 entitynum이 많은 레코드와 관련되어 있으므로 자체적으로 기본 키가 아니라는 것입니다. Advantage에서 ROWID psuedocolumn을 사용한 경험이 없습니다. 이것을 사용하는 방법에 대한 설명을 제공 할 수 있습니까? 다시 한 번 감사드립니다.
LuiCami

안녕하세요, ROWID에 대한 정보를 이미 찾았을 수도 있지만 아래 문서는이 의사 열의 기능을 이해하는 데 도움이되었습니다. devzone.advantagedatabase.com/dz/webhelp/Advantage10/…
hel

따라서 기본 키가 열 집합 인 경우 ROWID 대신 쉼표로 구분하면됩니다.
aroma

열 집합으로 더 복잡합니다. DB 서버가 데이터 유형으로 "row type"을 지원하는 경우 WHERE ROW (c1, c2, ..) IN (SELECT ROW (x, y, z) FROM ...)와 같은 방식으로 수행 할 수 있습니다. 그러나 DB가 ROW 유형을 지원하지 않는 경우 열을 단일 값 표현식 (예 : 열 연결)으로 변환해야합니다.
Alex W

27

두 번째 DELETE쿼리가 거의 정확했습니다. 사이에 테이블 이름 (또는 별칭)DELETEFROM입력하여 삭제할 테이블을 지정하십시오. 이것은 SELECT다른 답변과 같이 중첩 문을 사용하는 것보다 간단 합니다.

수정 된 쿼리 (옵션 1 : 전체 테이블 이름 사용) :

DELETE tableA
FROM tableA
INNER JOIN tableB u on (u.qlabel = tableA.entityrole AND u.fieldnum = tableA.fieldnum) 
WHERE (LENGTH(tableA.memotext) NOT IN (8,9,10)
OR tableA.memotext NOT LIKE '%/%/%')
AND (u.FldFormat = 'Date')

수정 된 쿼리 (옵션 2 : 별칭 사용) :

DELETE q
FROM tableA q
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%')
AND (u.FldFormat = 'Date')

여기에 더 많은 예 :
SQL Server에서 INNER JOIN을 사용하여 삭제하는 방법?


19

하지 말아야 할 것 :

DELETE FROM tableA WHERE entitynum IN (...your select...)

이제 비교없이 WHERE가 있습니다.

DELETE FROM tableA WHERE (...your select...)

따라서 최종 쿼리는 다음과 같습니다.

DELETE FROM tableA WHERE entitynum IN (
    SELECT tableA.entitynum FROM tableA q
      INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
    WHERE (LENGTH(q.memotext) NOT IN (8,9,10) OR q.memotext NOT LIKE '%/%/%')
      AND (u.FldFormat = 'Date')
)

응답 해 주셔서 감사합니다. 삭제하려는 항목의 개수를 계산하면 원래 의도 한 것보다 훨씬 많은 레코드가 생성되는 것 같습니다 (32061 대신 4598021). 나는 이것에 대한 나의 전문 지식 수준에 확실히 도달했습니다. 그 이유를 알고 있습니까? 내 계산 문은 다음과 같습니다. SELECT COUNT (*) FROM tableA WHERE entitynum IN (SELECT q.entitynum FROM tableA q INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) WHERE (LENGTH) (q.memotext) NOT IN (8,9,10) 또는 q.memotext NOT LIKE '% / % / %') AND (u.FldFormat = 'Date'));
LuiCami

4

이 시나리오에서 :

DELETE FROM tableA
WHERE (SELECT q.entitynum
FROM tableA q
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%')
AND (u.FldFormat = 'Date'));

비교하려는 열이 누락되지 않았습니까? 예:

DELETE FROM tableA
WHERE entitynum in (SELECT q.entitynum
FROM tableA q
INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) 
WHERE (LENGTH(q.memotext) NOT IN (8,9,10) 
OR q.memotext NOT LIKE '%/%/%')
AND (u.FldFormat = 'Date'));    

select 문에서 해당 열과 함께 삭제하려는 동일한 테이블에서 선택하기 때문에 해당 열이라고 가정합니다.


응답 해 주셔서 감사합니다. 삭제하려는 항목의 개수를 계산하면 원래 의도 한 것보다 훨씬 많은 레코드가 생성되는 것 같습니다 (32061 대신 4598021). 나는 이것에 대한 나의 전문 지식 수준에 확실히 도달했습니다. 그 이유를 알고 있습니까? 내 계산 문은 다음과 같습니다. SELECT COUNT (*) FROM tableA WHERE entitynum IN (SELECT q.entitynum FROM tableA q INNER JOIN tableB u on (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) WHERE (LENGTH) (q.memotext) NOT IN (8,9,10) 또는 q.memotext NOT LIKE '% / % / %') AND (u.FldFormat = 'Date'));
LuiCami

entitynum이 TableA에서 고유하지 않은 경우 (또는 기본 키) 많은 수는 확실히 가능합니다. 예를 들어 entitynum이 1 인 행이 여러 개있을 수 있지만 그중 하나만 조인 조건과 일치합니다. 그러나 'entitynum IN (SELECT ...)'조건은 entitynum이 1 인 모든 행을 반환합니다.
Alex W

내가 사용했던 선택은 레코드와 관련된 모든 열을 가져 오기 위해 다음과 같았으며 기본 키는 여전히 q.entitynum입니다. SELECT q. * FROM tableA q INNER JOIN tableB u on (u.qlabel = q .entityrole AND u.fieldnum = q.fieldnum) WHERE (LENGTH (q.memotext) NOT IN (8,9,10) OR q.memotext NOT LIKE '% / % / %') AND (u.FldFormat = 'Date ')
LuiCami

1

한 번 그렇게 했어.

CREATE TABLE exclusions(excl VARCHAR(250));
INSERT INTO exclusions(excl)
VALUES
       ('%timeline%'),
       ('%Placeholders%'),
       ('%Stages%'),
       ('%master_stage_1205x465%'),
       ('%Accessories%'),
       ('%chosen-sprite.png'),
('%WebResource.axd');
GO
CREATE VIEW ToBeDeleted AS 
SELECT * FROM chunks
       WHERE chunks.file_id IN
       (
       SELECT DISTINCT
             lf.file_id
       FROM LargeFiles lf
       WHERE lf.file_id NOT IN
             (
             SELECT DISTINCT
                    lf.file_id
             FROM LargeFiles lf
                LEFT JOIN exclusions e ON(lf.URL LIKE e.excl)
                WHERE e.excl IS NULL
             )
       );
GO
CHECKPOINT
GO
SET NOCOUNT ON;
DECLARE @r INT;
SET @r = 1;
WHILE @r>0

BEGIN
    DELETE TOP (10000) FROM ToBeDeleted;
    SET @r = @@ROWCOUNT  
END
GO
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.