如何在WHERE子句中使用SELECT语句编写SQL DELETE语句?

How to write a SQL DELETE statement with a SELECT statement in the WHERE clause?

数据库:Sybase Advantage 11

在我寻求规范化数据的过程中,我试图删除我从这个SELECT语句中得到的结果:

1
2
3
4
5
6
7
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声明:

1
2
3
4
5
6
7
8
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'))
;

当我尝试运行此语句时,我会不断收到此错误:

1
2
3
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.

我也尝试过这种说法:

1
2
3
4
5
6
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')
;

结果是:

1
2
3
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)

有人能帮助我正确地构造一个删除查询,从而删除正确的数据吗?


您需要在表A中标识主键,以便删除正确的记录。主键可以是单列,也可以是唯一标识表中某一行的多个列的组合。如果没有主键,则可以使用rowid伪列作为主键。

1
2
3
4
5
6
7
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'));


您的第二个DELETE查询几乎是正确的。只需确保将表名(或别名)放在DELETEFROM之间,以指定要从中删除的表。这比像在其他答案中那样使用嵌套的SELECT语句要简单。

已更正的查询(选项1:使用完整表名):

1
2
3
4
5
6
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:使用别名):

1
2
3
4
5
6
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的内部联接删除?


你不应该有:

1
DELETE FROM tableA WHERE entitynum IN (...your SELECT...)

现在你只需要一个没有比较的地方:

1
DELETE FROM tableA WHERE (...your SELECT...)

所以您的最终查询如下所示:

1
2
3
4
5
6
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')
)


在这种情况下:

1
2
3
4
5
6
7
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'));

是否缺少要与之比较的列?例子:

1
2
3
4
5
6
7
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语句中,您要从要用该列删除的同一个表中进行选择。


做过类似的事情:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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