Tsql 删除子记录,但仅删除没有子记录的父记录。Sql Server 2008

Tsql 删除子记录,但仅删除没有子记录的父记录。Sql Server 2008,tsql,sql-server-2008,Tsql,Sql Server 2008,不知道您能否帮我做一个简单的SQL查询 我已经包括了一个简单的脚本,用一些非常小的数据创建2个表和01 SP。有什么建议吗?谢谢 我有两张桌子 顾客 顾客 SQL查询应: 基于CustomerStoreID从CustomerItem表中删除所有项。 也删除客户,但仅当客户不再有子女时才删除 创建表和一些数据的脚本: BEGIN TRANSACTION; IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo

不知道您能否帮我做一个简单的SQL查询

我已经包括了一个简单的脚本,用一些非常小的数据创建2个表和01 SP。有什么建议吗?谢谢

我有两张桌子

顾客 顾客 SQL查询应:

基于CustomerStoreID从CustomerItem表中删除所有项。 也删除客户,但仅当客户不再有子女时才删除 创建表和一些数据的脚本:

BEGIN TRANSACTION;

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Customer]') AND type in (N'U'))
   DROP TABLE [dbo].[Customer]
GO

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Customer]
   ([CustomerID] [int] NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [Surname] [nvarchar](50) NOT NULL,

    CONSTRAINT [PK_Customer] 
    PRIMARY KEY CLUSTERED ([CustomerID] ASC)
   ) ON [PRIMARY]

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[CustomerItem]') AND type in (N'U'))
   DROP TABLE [dbo].[CustomerItem]
GO

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[CustomerItem]
   ([CustomerItemID] [int] NOT NULL,
    [CustomerID] [int] NOT NULL,
    [CustomerStoreID] [int] NOT NULL,
    [CustomerItemDescription] [nvarchar](50) NOT NULL,

    CONSTRAINT [PK_CustomerItem] 
    PRIMARY KEY CLUSTERED([CustomerItemID] ASC)
   ) ON [PRIMARY]
GO

INSERT INTO [dbo].[Customer]([CustomerID], [Name], [Surname])
   SELECT 1, N'John ', N'Smith' UNION ALL
   SELECT 2, N'Mark', N'Bloggs' UNION ALL
   SELECT 3, N'Richard', N'Lay'

INSERT INTO [dbo].[CustomerItem]([CustomerItemID], [CustomerID], [CustomerStoreID], [CustomerItemDescription])
   SELECT 1, 1, 1, N'BookOne' UNION ALL
   SELECT 2, 1, 1, N'BookTwo' UNION ALL
   SELECT 3, 1, 2, N'BookThree'UNION ALL
   SELECT 4, 1, 2, N'BookFour' UNION ALL
   SELECT 5, 2, 2, N'BookFive'UNION ALL
   SELECT 6, 2, 2, N'BookSix' UNION ALL
   SELECT 7, 3, 3, N'BookSeven' UNION ALL
   SELECT 8, 3, 3, N'BookEight'
GO

IF EXISTS (SELECT * FROM DBO.SYSOBJECTS WHERE id = OBJECT_ID(N'[dbo].[DeleteCustomerAndItemsByStoreId]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
   DROP PROCEDURE [dbo].[DeleteCustomerAndItemsByStoreId]
GO

CREATE PROCEDURE DeleteCustomerAndItemsByStoreId
                   @CustomerStoreID INT
/*
   Delete all customerItems  based on @CustomerStoreID
   Delete the customer itself when he not longer has customerItems
*/
AS
   DELETE FROM CustomerItem 
   WHERE CustomerStoreID = @CustomerStoreID

   ---Loop through the customer table and  Delete Customer if no longer has children
   --???
   COMMIT
基本上,在处理/删除最后一个客户项时,也会删除该客户

存储过程将只有一个参数@CustomerStoreID

delete Customer 
where not exists (select 1 
                  from CustomerItem 
         where  Customer.CustomerID = CustomerItem.CustomerID)
试试这个

delete Customer 
where not exists (select 1 
                  from CustomerItem 
         where  Customer.CustomerID = CustomerItem.CustomerID)

基本上,您的存储过程应该如下所示:

CREATE PROCEDURE DeleteCustomerAndItemsByStoreId
                    @CustomerStoreID INT
AS
   DECLARE @CustomerIDs TABLE(CustomerID INT)

   -- do the first delete and output the deleted CustomerID's into a table variable
   DELETE CustomerItem 
   OUTPUT DELETED.CustomerID INTO @CustomerIDs(CustomerID)
   WHERE CustomerStoreID = @CustomerStoreID

   -- delete from the Customer table when no CustomerItems exist anymore for that CustomerID
   DELETE dbo.Customer
   OUTPUT DELETED.CustomerID 
   FROM @CustomerIDs c
   WHERE
      dbo.Customer.CustomerID = c.CustomerID
      AND NOT EXISTS(SELECT * FROM dbo.CustomerItem WHERE CustomerID = c.CustomerID)
这应该执行两步删除-首先删除定义的CustomerStoreID的所有CustomerItem行,然后从受第一次删除影响的客户集中删除那些没有更多CustomerItem条目的客户

更新:当我运行此命令时:

SELECT * FROM customer

EXEC DeleteCustomerAndItemsByStoreId @CustomerStoreID = 2

SELECT * FROM customer
我得到:

CustomerID  Name       Surname
   1        John        Smith
   2        Mark        Bloggs
   3        Richard     Lay

CustomerID     -- that from the "OUTPUT Deleted.CustomerID"
    2

CustomerID  Name       Surname
   1        John        Smith
   3        Richard     Lay

2号客户不见了-这与您的脚本、数据有关

基本上,您的存储过程应该如下所示:

CREATE PROCEDURE DeleteCustomerAndItemsByStoreId
                    @CustomerStoreID INT
AS
   DECLARE @CustomerIDs TABLE(CustomerID INT)

   -- do the first delete and output the deleted CustomerID's into a table variable
   DELETE CustomerItem 
   OUTPUT DELETED.CustomerID INTO @CustomerIDs(CustomerID)
   WHERE CustomerStoreID = @CustomerStoreID

   -- delete from the Customer table when no CustomerItems exist anymore for that CustomerID
   DELETE dbo.Customer
   OUTPUT DELETED.CustomerID 
   FROM @CustomerIDs c
   WHERE
      dbo.Customer.CustomerID = c.CustomerID
      AND NOT EXISTS(SELECT * FROM dbo.CustomerItem WHERE CustomerID = c.CustomerID)
delete c
from [Customer] as c
    left join [CustomerItem] as ci
    on ci.[CustomerID] = c.[CustomerID]
where ci.[CustomerID] is null;
这应该执行两步删除-首先删除定义的CustomerStoreID的所有CustomerItem行,然后从受第一次删除影响的客户集中删除那些没有更多CustomerItem条目的客户

更新:当我运行此命令时:

SELECT * FROM customer

EXEC DeleteCustomerAndItemsByStoreId @CustomerStoreID = 2

SELECT * FROM customer
我得到:

CustomerID  Name       Surname
   1        John        Smith
   2        Mark        Bloggs
   3        Richard     Lay

CustomerID     -- that from the "OUTPUT Deleted.CustomerID"
    2

CustomerID  Name       Surname
   1        John        Smith
   3        Richard     Lay

2号客户不见了-这是您的脚本,您的数据

作为旁注:如果您发现这些检查过于复杂。。。。。对于一个表,请尝试以下操作:如果存在,请从sys.tables中选择*,其中name='Customer',对于一个过程,请使用sys.procedures目录视图-这比一般的sys.objects要容易得多,然后必须指定要查找的对象类型,我认为….作为旁注:如果发现这些检查,您会做得过于复杂。。。。。对于一个表,请尝试以下操作:如果存在,请从sys.tables中选择*,其中name='Customer',对于一个过程,请使用sys.procedures目录视图-比一般的sys.objects更易于使用,然后必须指定要查找的对象类型,我认为….是customerstoreID 1,有两个客户。这就是为什么我像以前一样创建了我的答案。非常感谢您的回复和时间。我已尝试了您的查询,但如果执行EXEC[dbo].[DeleteCustomerAndItemSystoreId]@CustomerStoreID=2,则该查询似乎不起作用。我仍然在表中看到customerID=2的客户,因为它应该显示出来。基本上,我需要删除属于customerID的所有customerItems,当customerID没有更多的子项时,也将其删除。是的customerstoreID 1,有2个客户。这就是为什么我像以前一样创建了我的答案。非常感谢您的回复和时间。我已尝试了您的查询,但如果执行EXEC[dbo].[DeleteCustomerAndItemSystoreId]@CustomerStoreID=2,则该查询似乎不起作用。我仍然在表中看到customerID=2的客户,因为它应该显示出来。基本上,我需要删除属于customerID的所有customerItems,并且当customerID没有更多的子项时,也删除这些子项。我假设他的意思是删除customerItems中受第一次删除影响的客户-不是所有客户,而是所有客户他们,你的代码当然工作得很好!他需要一个反向级联删除:-我假设他的意思是删除那些受CustomerItems中第一次删除影响的客户-不是所有客户,但对于所有客户,您的代码肯定工作得很好!他需要一个反向级联删除:-谢谢你的工作!!感谢大家的投入和时间。如果没有,很抱歉clear@Beth,我无法编辑您的答案,因为我的编辑只有一个字符。。但是您应该编写select distinct c.CustomerID,否则您可能会得到错误的模棱两可的列名谢谢您的工作!!感谢大家的投入和时间。如果没有,很抱歉clear@Beth,我无法编辑您的答案,因为我的编辑只有一个字符。。但是您应该编写selectdistinct c.CustomerID,否则您可能会得到错误的不明确的列名
delete c
from [Customer] as c
    left join [CustomerItem] as ci
    on ci.[CustomerID] = c.[CustomerID]
where ci.[CustomerID] is null;