39

Baza: Sybase Advantage 11Jak napisać instrukcję DELETE SQL za pomocą instrukcji SELECT w klauzuli WHERE?

Na moim dążeniu do normalizacji danych, próbuję usunąć wyniki dostaję od tego SELECT stwierdzeniem:

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') 
; 

To stwierdzenie DELETE I mają pochodzić z:

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')) 
; 

ja ciągle ten błąd, gdy próbuję uruchomić to oświadczenie:

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. 

Próbowałem również to stwierdzenie:

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') 
; 

co skutkuje:

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) 

Może ktoś mi pomóc w odpowiednio konstruując DELETE że spowoduje odpowiednie dane są usuwane?

+0

Najgorszy scenariusz - można utworzyć tabelę tymczasową, SELECT w tej tabeli tymczasowej, wykonać usuwać przystąpienie do tabeli tymczasowej, a następnie Droping tabeli tymczasowej? –

Odpowiedz

73

Musisz zidentyfikować klucz podstawowy w tabeli A, aby usunąć poprawny rekord. Klucz podstawowy może być pojedynczą kolumną lub kombinacją kilku kolumn, które jednoznacznie identyfikują wiersz w tabeli. Jeśli nie ma klucza podstawowego, pseudo kolumna ROWID może być używana jako klucz podstawowy.

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')); 
+0

Dziękuję Alex za szybką odpowiedź. @AlexW Myślę, że uderzyłeś paznokciem w głowę. Sposób działania tej tabeli polega na tym, że entitynum jest powiązane z wieloma rekordami i jako takie nie jest kluczem podstawowym samym w sobie. Nie mam doświadczenia z używaniem ROWID psuedocolumn w Advantage. Czy możesz podać wyjaśnienie, jak tego użyć? Dzięki jeszcze raz. – LuiCami

+0

Dziękuję @AlexW To działało cudownie !! – LuiCami

9

nie powinien mieć:

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

Teraz wystarczy mieć gdzie za bez porównania:

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

Więc twój ostateczny zapytanie będzie wyglądać następująco;

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') 
) 
+0

dziękuję za odpowiedź.Wygląda na to, że gdy przeprowadzę obliczenia tego, co zamierzałem usunąć, otrzymam więcej rekordów niż pierwotnie zamierzano (4598021 zamiast 32061). Zdecydowanie osiągnąłem poziom mojego doświadczenia w tej dziedzinie. Czy znasz przyczynę takiego stanu rzeczy? Polecenie count wygląda następująco: SELECT COUNT (*) FROM tableA WHERE entitynum IN (WYBIERZ q.entitynum FROM tableA q table INNER JOIN (u.qlabel = q.entityrole AND u.fieldnum = q.fieldnum) GDZIE (DŁUGOŚĆ) (q.memotext) NOT IN (8,9,10) LUB q.memotext NOT LIKE '% /% /%' AND AND (u.FldFormat = 'Date')); – LuiCami

3

w tym scenariuszu: nie

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')); 

czy brakuje kolumny, które chcesz porównać do? Przykład:

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'));  

Zakładam, że jest to kolumna, ponieważ w swojej select jesteś wybierając z tej samej tabeli jesteś chcą usunąć ze z tej kolumny.

+0

dziękuję za odpowiedź. Wygląda na to, że gdy przeprowadzę obliczenia tego, co zamierzałem usunąć, otrzymam więcej rekordów niż pierwotnie zamierzano (4598021 zamiast 32061). Zdecydowanie osiągnąłem poziom mojego doświadczenia w tej dziedzinie. Czy znasz przyczynę takiego stanu rzeczy? Moja instrukcja zliczania wyglądała następująco: WYBIERZ LICZBĘ (*) Z tabeliA GDZIE JASNO IN (WYBIERZ q.entitynum Z tabeliA q Tabela INNER JOINB u na (u.qlabel = q.entityrole I u.fieldnum = q.fieldnum) GDZIE (DŁUGOŚĆ (q.memotekst) NIE IN (8,9,10) LUB q.memotekst NIE PODOBA "% /% /%") ORAZ (u.FldFormat = "Data")) ; – LuiCami

+0

ten wybór daje prawidłowe wartości do usunięcia? – Andres

+0

Duża liczba jest z pewnością możliwa, jeśli entitynum nie jest unikatowy (lub klucz podstawowy) w TableA. Na przykład może istnieć kilka wierszy z entitynum równym 1, ale tylko jeden z nich jest zgodny z warunkiem łączenia. Jednak warunek "entitynum IN (SELECT ...)" zwróci wszystkie wiersze z entitynum jest równe 1. –

1

Czy coś takiego kiedyś:

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 
4

I manipulowane swoją 2nd kwerendy, aby to działało. Myślę, że jest to bardziej proste niż użycie zagnieżdżonej instrukcji SELECT, jak w innych odpowiedziach.

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') 

Więcej szczegółów tutaj:
How to Delete using INNER JOIN with SQL Server?