如何在 WHERE 子句中编写带有 SELECT 语句的 SQL DELETE 语句?
Posted
技术标签:
【中文标题】如何在 WHERE 子句中编写带有 SELECT 语句的 SQL DELETE 语句?【英文标题】:How to write a SQL DELETE statement with a SELECT statement in the WHERE clause? 【发布时间】:2013-07-07 02:10:38 【问题描述】:数据库: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)
有人可以帮助我正确构建删除正确数据的查询吗?
【问题讨论】:
最坏的情况——你能创建一个临时表,选择到那个临时表,你的删除加入临时表,然后删除临时表吗? 【参考方案1】:你不应该有:
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)。我肯定已经达到了我在这方面的专业水平。你知道为什么会这样吗?我的计数语句如下所示: 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) NOT IN (8,9,10) OR q.memotext NOT LIKE '%/%/%') AND (u.FldFormat = 'Date')) ;【参考方案2】:在这种情况下:
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)。我肯定已经达到了我在这方面的专业水平。你知道为什么会这样吗?我的计数语句如下所示: 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) NOT IN (8,9,10) OR q.memotext NOT LIKE '%/%/%') AND (u.FldFormat = 'Date')) ; 如果entitynum 在TableA 中不是唯一的(或主键),大计数当然是可能的。例如,可能有几行 entitynum 等于 1,但其中只有一个符合连接条件。但是条件 'entitynum IN ( SELECT ... )' 将返回 entitynum 等于 1 的所有行。 我一直使用的选择是以下获取与记录关联的所有列,主键仍然是 q.entitynum: SELECT 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 = '日期')【参考方案3】:您需要识别 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'));
【讨论】:
感谢 Alex 的快速回复。 @AlexW 我认为您一针见血。该表的工作方式是 entitynum 与许多记录相关,因此它本身不是主键。我没有在 Advantage 中使用 ROWID 伪列的经验。你能解释一下如何使用它吗?再次感谢。 您好,您可能已经找到了关于 ROWID 的信息,但是下面的文章有助于我理解这个伪列背后的功能。 devzone.advantagedatabase.com/dz/webhelp/Advantage10/… 所以如果主键是一组列,我可以简单地将它们用逗号分隔而不是 ROWID? 一组列比较复杂。如果数据库服务器支持“行类型”作为数据类型,您可以使用 WHERE ROW (c1, c2, ..) IN (SELECT ROW (x, y, z) FROM ...) 之类的东西。但是,如果 DB 不支持 ROW 类型,则必须将列转换为单值表达式,例如 - 列连接。【参考方案4】:曾经做过类似的事情:
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
【讨论】:
【参考方案5】:您的第二个DELETE
查询几乎是正确的。只需确保将表名(或别名)放在DELETE
和FROM
之间,以指定要从哪个表中删除。这比在其他答案中使用嵌套的 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')
更多示例:How to Delete using INNER JOIN with SQL Server?
【讨论】:
【参考方案6】:在我的项目中,我曾经删除重复项。 (В своем проекте использовал для удаления дублей)
DELETE
FROM
a_send
WHERE
send_id IN (
SELECT
PR.dd
FROM
( SELECT MAX(send_id) as dd, COUNT ( 1 ) AS qty, phone_id FROM "a_send" GROUP BY phone_id ) AS PR
WHERE
PR.qty > 1
)
注意为了不删除公国的所有记录,请使用MAX (send_id)
(обратите внимание для того чтобы в приниципе не удалилесь все записи пользовал MAX(send_id)
)
【讨论】:
你能把你的文字翻译成英文吗!?以上是关于如何在 WHERE 子句中编写带有 SELECT 语句的 SQL DELETE 语句?的主要内容,如果未能解决你的问题,请参考以下文章
如何在带有 select 语句的 where 子句中使用比较运算符?
在 WHERE 子句中使用函数编写 SQL SELECT 语句是不是有 Django 等效项?