Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从没有相关数据的表中删除-其中不在,并且连接失败_Sql_Sql Server_Join_Where_Sql Delete - Fatal编程技术网

Sql 从没有相关数据的表中删除-其中不在,并且连接失败

Sql 从没有相关数据的表中删除-其中不在,并且连接失败,sql,sql-server,join,where,sql-delete,Sql,Sql Server,Join,Where,Sql Delete,考虑下表结构: 我正在创建一个存储过程,它将从RelatedA和RelatedB中删除数据。之后,我想从主数据中删除所有在中不再有关联的RelatedA和RelatedB中的内容 我尝试了3种不同的查询来获取要删除的ID 使用简单的WHERE 在WHERE 使用join+在ON 所有这些都不会返回任何记录进行删除,而且我确信有几个原因是我刚刚在主数据中插入了新记录(并且没有在相关表中插入数据的触发器) 我实际上有两个问题: 我做错了什么? 我的问题之间的确切区别是什么?(奖金) 您只需对父查询

考虑下表结构:

我正在创建一个存储过程,它将从
RelatedA
RelatedB
中删除数据。之后,我想从
主数据
中删除所有在中不再有关联的
RelatedA
RelatedB
中的内容

我尝试了3种不同的查询来获取要删除的ID

使用简单的
WHERE
WHERE
使用join+
ON
所有这些都不会返回任何记录进行删除,而且我确信有几个原因是我刚刚在
主数据
中插入了新记录(并且没有在相关表中插入数据的触发器)

我实际上有两个问题:

  • 我做错了什么?
  • 我的问题之间的确切区别是什么?(奖金)

  • 您只需对父查询执行
    而不在
    中。因此,从这个开始,它应该为您提供两个相关表中都没有匹配项的所有记录。这是您的第一个查询所做的

    SELECT * 
    FROM MasterData
    WHERE ID NOT IN (SELECT MasterDataID FROM RelatedA)
    AND ID NOT IN (SELECT MasterDataID FROM RelatedB)
    
    然后将其更改为删除:

    DELETE MasterData
    FROM MasterData
    WHERE ID NOT IN (SELECT MasterDataID FROM RelatedA)
    AND ID NOT IN (SELECT MasterDataID FROM RelatedB)
    
    并用一些实际值进行测试:

    --Create tables
    DECLARE @MasterData TABLE (ID BIGINT)
    DECLARE @RelatedA TABLE (ID BIGINT, MasterDataID BIGINT)
    DECLARE @RelatedB TABLE (ID BIGINT, MasterDataID BIGINT)
    
    --Some test data
    INSERT INTO @MasterData VALUES (1),(2),(3),(4),(5)
    INSERT INTO @RelatedA VALUES (1,1),(2,2)
    INSERT INTO @RelatedB VALUES (1,3),(2,4)
    
    SELECT * FROM @MasterData --5 rows
    
    --Do the delete
    DELETE @MasterData 
    FROM @MasterData MD
    WHERE MD.ID NOT IN (SELECT MasterDataID FROM @RelatedA)
    AND MD.ID NOT IN (SELECT MasterDataID FROM @RelatedB)
    
    SELECT * FROM @MasterData --4 rows
    

    您只需对父查询执行
    而不在
    中。因此,从这个开始,它应该为您提供两个相关表中都没有匹配项的所有记录。这是您的第一个查询所做的

    SELECT * 
    FROM MasterData
    WHERE ID NOT IN (SELECT MasterDataID FROM RelatedA)
    AND ID NOT IN (SELECT MasterDataID FROM RelatedB)
    
    然后将其更改为删除:

    DELETE MasterData
    FROM MasterData
    WHERE ID NOT IN (SELECT MasterDataID FROM RelatedA)
    AND ID NOT IN (SELECT MasterDataID FROM RelatedB)
    
    并用一些实际值进行测试:

    --Create tables
    DECLARE @MasterData TABLE (ID BIGINT)
    DECLARE @RelatedA TABLE (ID BIGINT, MasterDataID BIGINT)
    DECLARE @RelatedB TABLE (ID BIGINT, MasterDataID BIGINT)
    
    --Some test data
    INSERT INTO @MasterData VALUES (1),(2),(3),(4),(5)
    INSERT INTO @RelatedA VALUES (1,1),(2,2)
    INSERT INTO @RelatedB VALUES (1,3),(2,4)
    
    SELECT * FROM @MasterData --5 rows
    
    --Do the delete
    DELETE @MasterData 
    FROM @MasterData MD
    WHERE MD.ID NOT IN (SELECT MasterDataID FROM @RelatedA)
    AND MD.ID NOT IN (SELECT MasterDataID FROM @RelatedB)
    
    SELECT * FROM @MasterData --4 rows
    

    第一个应该有效。第二个缺少“左联接”,它将与不存在的行不匹配:

    SELECT MD.ID
    FROM MasterData MD
       LEFT JOIN RelatedA RelA on RelA.MasterDataID = MD.ID
       LEFT JOIN RelatedB RelB on RelB.MasterDataID = MD.ID
    WHERE RelA.MasterDataID IS NULL
      AND RelB.MasterDataID IS NULL
    

    第一个应该有效。第二个缺少“左联接”,它将与不存在的行不匹配:

    SELECT MD.ID
    FROM MasterData MD
       LEFT JOIN RelatedA RelA on RelA.MasterDataID = MD.ID
       LEFT JOIN RelatedB RelB on RelB.MasterDataID = MD.ID
    WHERE RelA.MasterDataID IS NULL
      AND RelB.MasterDataID IS NULL
    

    首先让我们看看那些不起作用的

    DELETE FROM MasterData
    WHERE ID IN (
        SELECT MD.ID
        FROM MasterData MD
          JOIN RelatedA RelA on RelA.MasterDataID = MD.ID
          JOIN RelatedB RelB on RelB.MasterDataID = MD.ID
        WHERE RelA.MasterDataID IS NULL
          AND RelB.MasterDataID IS NULL
    )
    
    WHERE
    条件永远不会为真,因为您正在进行内部联接而不是左联接


    联接条件永远不会为true,因为
    null
    不等于
    null
    (即
    null
    =
    null
    返回
    null
    而不是true),第二部分要求
    MasterDataID
    为null


    这包括一个不必要的子查询,但除非我遗漏了一些东西,否则它应该可以工作。您可以将子查询重写为(同样,您也可以在上面的前两个查询中省略子查询)

    就我个人而言,我宁愿不存在

    DELETE FROM MasterData MD
    WHERE NOT EXISTS (SELECT 1 FROM RelatedA WHERE MasterDataID = MD.ID)
    AND NOT EXISTS (SELECT 1 FROM RelatedB WHERE MasterDataID = MD.ID)
    

    首先让我们看看那些不起作用的

    DELETE FROM MasterData
    WHERE ID IN (
        SELECT MD.ID
        FROM MasterData MD
          JOIN RelatedA RelA on RelA.MasterDataID = MD.ID
          JOIN RelatedB RelB on RelB.MasterDataID = MD.ID
        WHERE RelA.MasterDataID IS NULL
          AND RelB.MasterDataID IS NULL
    )
    
    WHERE
    条件永远不会为真,因为您正在进行内部联接而不是左联接


    联接条件永远不会为true,因为
    null
    不等于
    null
    (即
    null
    =
    null
    返回
    null
    而不是true),第二部分要求
    MasterDataID
    为null


    这包括一个不必要的子查询,但除非我遗漏了一些东西,否则它应该可以工作。您可以将子查询重写为(同样,您也可以在上面的前两个查询中省略子查询)

    就我个人而言,我宁愿不存在

    DELETE FROM MasterData MD
    WHERE NOT EXISTS (SELECT 1 FROM RelatedA WHERE MasterDataID = MD.ID)
    AND NOT EXISTS (SELECT 1 FROM RelatedB WHERE MasterDataID = MD.ID)
    

    我建议使用
    notexists

    select
          md.*
    from MasterData md
    where not exists (
        select 1 from RelatedA A where md.id = A.MasterDataID)
    and not exists (
        select 1 from RelatedB B where md.id = B.MasterDataID)
    ;
    
    将这些数据一起使用(如上所示)或单独使用以评估数据。如果满足此条件,它将很容易转换为删除查询


    我建议使用
    不存在

    select
          md.*
    from MasterData md
    where not exists (
        select 1 from RelatedA A where md.id = A.MasterDataID)
    and not exists (
        select 1 from RelatedB B where md.id = B.MasterDataID)
    ;
    
    将这些数据一起使用(如上所示)或单独使用以评估数据。如果满足此条件,它将很容易转换为删除查询


    如果运行子查询,子查询是否返回数据?(即,
    SELECT…
    bit)@DavidG我的意思是,就我的问题而言,我目前正在测试这些。更新了我的问题以更好地反映这一点。请尝试在SQL Fiddle、jsut中复制这一点,用于
    WHERE。。不在
    示例中。它应该可以工作。非常确定第一个应该可以工作。如果运行子查询,子查询会返回数据吗?(即,
    SELECT…
    bit)@DavidG我的意思是,就我的问题而言,我目前正在测试这些。更新了我的问题以更好地反映这一点。请尝试在SQL Fiddle、jsut中复制这一点,用于
    WHERE。。不在
    示例中。应该行得通。第一个肯定行得通。是不是我的数据库严重堵塞了?我现在正在用一个表测试您的第二个两个查询,当我使用
    where not in
    时,我没有记录,而使用
    where not exists
    时,我得到所有记录。到底发生了什么事?@MDeSchaepmeester不确定,
    不在
    不存在
    查询应该返回相同的数据只有
    不存在
    目前似乎有效。我不能用
    不在
    中正确地获得它,我做的和你做的完全一样。如果这被证明是数据库的完整性问题,我不会感到惊讶,因为它在几年前投入使用后,实际上没有得到维护……对于大型子查询来说,“不存在”通常更快,所以可能“不存在”只是需要很长时间?奇怪的是查询“成功执行”在大约3秒钟内,而它应该需要更多的时间(这里谈论的是成百上千条记录)。可能是某个查询优化器的“bug”?可能是我的数据库严重堵塞了吗?我现在正在用一个表测试您的第二个两个查询,当我使用
    where not in
    时,我没有记录,而使用
    where not exists
    时,我得到所有记录。到底发生了什么事?@MDeSchaepmeester不确定,
    不在
    不存在
    查询应该返回相同的数据只有
    不存在
    目前似乎有效。我不能用
    不在
    中正确地获得它,我做的和你做的完全一样。如果这被证明是数据库的完整性问题,我不会感到惊讶,因为它在几年前投入使用后,实际上没有得到维护……对于大型子查询,“不存在”通常更快,所以“不存在”可能只是需要很长时间?奇怪的是