39

База данных: Sybase Advantage 11Как написать инструкцию SQL DELETE с инструкцией SELECT в предложении WHERE?

В своем стремлении нормализовать данные, я пытаюсь удалить результаты, которые я получаю от этого 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) 

Может кто-то помочь мне правильно построению УДАЛИТЬ запрос, который приведет в соответствующих данных удаляются?

+0

Наихудший сценарий - вы можете создать временную таблицу, ВЫБРАТЬ в эту временную таблицу, сделать ваш удалить присоединение к временной таблице, а затем Droping временной таблицы? –

ответ

73

Чтобы удалить правильную запись, вам необходимо определить первичный ключ в таблицеA. Первичным ключом может быть один столбец или комбинация из нескольких столбцов, которые однозначно идентифицируют строку в таблице. Если первичного ключа нет, в качестве первичного ключа может использоваться псевдо-столбец 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')); 
+0

Спасибо, Алекс за быстрый ответ. @AlexW Я думаю, вы ударили ноготь по голове. Способ работы этой таблицы состоит в том, что entitynum связан со многими записями и, как таковой, сам по себе не является первичным ключом. У меня нет опыта использования ROWID psuedocolumn в Advantage. Не могли бы вы объяснить, как это использовать? Еще раз спасибо. – LuiCami

+0

Спасибо @AlexW Это сработало чудесно !! – LuiCami

9

Если вы не имеете:

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

Благодарю вас за ответ.Кажется, что, когда я запускаю счет того, что собираюсь удалить, я получаю гораздо больше записей, чем первоначально предполагалось (4598021 вместо 32061). Я определенно достиг своего уровня знаний об этом. Вы знаете причину этого? Оператор подсчета выглядит так: 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) ГДЕ (ДЛИНА (q.memotext) NOT IN (8,9,10) ИЛИ q.memotext НЕ НРАВИТСЯ «% /% /%») И (u.FldFormat = 'Дата')); – LuiCami

3

в этом сценарии:

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

Я полагаю, что это столбец, так как в вашем отборном заявлении вы выбираете из той же таблицы вы желающая удалить из с этой колонкой.

+0

Благодарим вас за ответ. Кажется, что, когда я запускаю счет того, что собираюсь удалить, я получаю гораздо больше записей, чем первоначально предполагалось (4598021 вместо 32061). Я определенно достиг своего уровня знаний об этом. Вы знаете причину этого? Оператор подсчета выглядит так: 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) ГДЕ (ДЛИНА (q.memotext) НЕ В (8,9,10) ИЛИ q.memotext НЕ НРАВИТСЯ «% /% /%») И (u.FldFormat = 'Дата')) ; – LuiCami

+0

этот выбор дает вам правильные значения для удаления? – Andres

+0

Большой счет, конечно, возможен, если entitynum не уникален (или первичный ключ) в TableA. Например, может быть несколько строк, где entitynum равно 1, но только одно из них соответствует условию объединения. Однако условие «entitynum IN (SELECT ...)» вернет все строки с сущностью равными 1. –

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 
4

Я подправил свой 2-й запрос, чтобы заставить его работать. Я думаю, что это более прямолинейно, чем использование вложенного оператора SELECT, как в других ответах.

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

Более подробно здесь:
How to Delete using INNER JOIN with SQL Server?

Смежные вопросы