Удалите детей, но удалите родительскую запись только там, где нет детей. SQL Server 2008 - PullRequest
0 голосов
/ 21 марта 2011

Хотите знать, можете ли вы помочь мне с простым запросом SQL.

Я включил простой скрипт для создания 2 таблиц и 01 SP.С некоторыми очень маленькими данными.Какие-либо предложения?Спасибо

У меня есть 2 таблицы

  • Customer
  • CustomerItem

Запрос SQL должен:

  1. Удалите все элементы из таблицы CustomerItem на основе CustomerStoreID.
  2. Удалите также и клиента, но только когда у него больше нет детей

Скрипт для создания таблиц инекоторые данные:

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

В основном при обработке / удалении последних customerItem также удаляют клиента.

Хранимая процедура будет иметь только один параметр @CustomerStoreID

Ответы [ 4 ]

2 голосов
/ 21 марта 2011
delete c
from [Customer] as c
    left join [CustomerItem] as ci
    on ci.[CustomerID] = c.[CustomerID]
where ci.[CustomerID] is null;
2 голосов
/ 21 марта 2011
delete from Customer where CustomerID in
(select distinct CustomerID 
 from customer c left outer join CustomerItem i 
  on c.CustomerID = i.CustomerID
 where i.CustomerID is null)
1 голос
/ 21 марта 2011

попробуйте

delete Customer 
where not exists (select 1 
                  from CustomerItem 
         where  Customer.CustomerID = CustomerItem.CustomerID)
0 голосов
/ 21 марта 2011

По сути, ваш сохраненный процесс должен выглядеть примерно так:

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)

Это должно сделать двухэтапное удаление - сначала удалите все CustomerItem строки для определенного CustomerStoreID, а затем удалите тех клиентов из этого набора клиентов, затронутых первым удалением, у которых больше нет 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 прошло - это с твоим сценарием, твои данные

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...