39

database: Advantage Sybase 11Come scrivere un'istruzione SQL DELETE con un'istruzione SELECT nella clausola WHERE?

Sulla mia ricerca per normalizzare i dati, sto cercando di eliminare i risultati che ottengo da questa SELECT dichiarazione:

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

Questa è la dichiarazione DELETE sono venuto su con:

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

io continuo ottengo questo errore quando provo a fare funzionare questa dichiarazione:

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. 

Ho anche provato questa affermazione:

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

che si traduce in:

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) 

Qualcuno mi potrebbe aiutare a costruire correttamente una query DELETE che si tradurrà in dati corretti di essere rimosso?

+0

peggiore delle ipotesi - si può creare una tabella temporanea, SELEZIONA in quella tabella temporanea, fare la tua eliminare unendo la tabella temporanea, quindi droping la tabella temporanea? –

risposta

73

È necessario identificare la chiave primaria in TabellaA per eliminare il record corretto. La chiave primaria può essere una singola colonna o una combinazione di più colonne che identifica in modo univoco una riga nella tabella. Se non esiste una chiave primaria, la pseudo colonna ROWID può essere utilizzata come chiave primaria.

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

Grazie Alex per la rapida risposta. @AlexW Penso che tu abbia colpito il chiodo sulla testa. Il modo in cui questa tabella funziona è che l'entitynum è correlato a molti record e in quanto tale non è una chiave primaria in sé e per sé. Non ho esperienza con l'utilizzo del ROWID psuedocolumn in Advantage. Potresti fornire una spiegazione su come usarlo? Grazie ancora. – LuiCami

+0

Grazie @AlexW Questo ha funzionato meravigliosamente !! – LuiCami

9

Non dovresti avere:

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

Ora basta avere un WHERE senza confronto:

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

Quindi la query finale sarebbe simile a questa;

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

grazie per la risposta.Sembra che quando eseguo un conteggio di quello che stavo per cancellare, finisco con molti più dischi di quelli originariamente previsti (4598021 invece di 32061). Ho sicuramente raggiunto il mio livello di esperienza su questo. Sai la ragione per cui questo sarebbe il caso? La mia affermazione contava così: 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) NON IN (8,9,10) O q.memotext NON MI PIACE '% /% /%') E (u.FldFormat = 'Data')); – LuiCami

3

in questo scenario: non

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

Vi manca la colonna che si desidera confrontare? Esempio:

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

Penso che sia quella colonna poiché nella vostra dichiarazione prescelta si sta selezionando dalla stessa tabella hai intenzione di eliminare dalla con quella colonna.

+0

grazie per la risposta. Sembra che quando eseguo un conteggio di quello che stavo per cancellare, finisco con molti più dischi di quelli originariamente previsti (4598021 invece di 32061). Ho sicuramente raggiunto il mio livello di esperienza su questo. Sai la ragione per cui questo sarebbe il caso? La mia affermazione contava come segue: 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) DOVE (LUNGHEZZA (q.memotext) NON IN (8,9,10) O q.memotext NON MI PIACE '% /% /%') E (u.FldFormat = 'Data')) ; – LuiCami

+0

questa selezione fornisce i valori corretti da eliminare? – Andres

+0

Il conteggio grande è certamente possibile se entitynum non è univoco (o chiave primaria) in TableA. Per esempio, possono esserci più righe con entitynum uguale a 1 ma solo una di esse corrisponde alla condizione di join. Tuttavia la condizione 'entitynum IN (SELECT ...)' restituirà tutte le righe con entitynum uguale a 1. –

1

fatto qualcosa di simile che, una volta:

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

ho ottimizzato la vostra seconda query per farlo funzionare. Penso che sia più semplice dell'uso di un'istruzione nidificata SELECT come nelle altre risposte.

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

Maggiori dettagli qui:
How to Delete using INNER JOIN with SQL Server?

Problemi correlati