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


78

数据库: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。

Answers:


140

您需要在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伪列的经验。您能否提供有关如何使用此功能的说明?再次感谢。
LuiCami

嗨,也许您已经找到了有关ROWID的信息,但是下面的文章对我了解此伪列背后的功能很有帮助。devzone.advantagedatabase.com/dz/webhelp/Advantage10/…–
hel

因此,如果主键是一组列,我可以简单地将它们用逗号分隔而不是ROWID?

使用一组列会更加复杂。如果数据库服务器支持将“行类型”作为数据类型,则可以使用WHERE ROW(c1,c2,..)IN(SELECT ROW(x,y,z)FROM ...)这样的操作来实现。但是,如果数据库不支持ROW类型,则必须将列转换为单个值表达式,例如-列的串联。
Alex W

26

您的第二个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进行删除?


18

您不应该拥有:

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

感谢您的答复。似乎当我计算要删除的内容时,最终得到的记录要多于最初的预期(4598021,而不是32061)。我在这方面绝对达到了我的专业水平。您知道这种情况的原因吗?我的计数语句看起来像这样:从表A的SELECT COUNT(*)实体num输入(从表A的q.entitynum选择q INNER JOIN tableB u在(u.qlabel = q.entityrole和u.fieldnum = q.fieldnum)在哪里(长度(q.memotext)不是IN(8,9,10)或q.memotext不是'%/%/%')AND(u.FldFormat ='Date')));
LuiCami 2013年

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语句中,您是从要从该表中删除的同一张表中进行选择。


感谢您的答复。似乎当我计算要删除的内容时,最终得到的记录要多于最初的预期(4598021,而不是32061)。我在这方面绝对达到了我的专业水平。您知道这种情况的原因吗?我的计数语句看起来像这样:从表A的SELECT COUNT(*)实体num输入(从表A的q.entitynum选择q INNER JOIN tableB u on(u.qlabel = q.entityrole和u.fieldnum = q.fieldnum)在哪里(长度(q.memotext)不是IN(8,9,10)或q.memotext不是'%/%/%')AND(u.FldFormat ='Date')));
LuiCami 2013年

如果在TableA中entitynum不是唯一的(或主键),则大数目当然是可能的。例如,可能存在几行,entitynum等于1,但只有其中之一与联接条件匹配。但是条件“entitynum IN(SELECT ...)”将返回所有与entitynum行等于1
亚历W¯¯

我一直在使用的选择是以下所有与记录相关联的列,主键仍然是q.entitynum:SELECT q。* FROM tableA q INNER JOIN tableB u on(u.qlabel = q .entityrole和u.fieldnum = q.fieldnum)(LENGTH(q.memotext)不在(8,9,10)或q.memotext不像'%/%/%')和(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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.