2017-09-05 44 views
1

我有要求將同一父記錄複製到同一表的N個子項。 數據中的唯一區別是父母標識和客戶標識,我必須將父級記錄複製到只有ParentId和ClientId值更改的子級。 - 父記錄可能是1到2000,需要爲每個客戶端移動。 - 兒童記錄(重複1至1000)不同的孩子。如何使用MS SQL將相同表中的父項記錄複製到子項CTE

我已經實現了使用SQL Server Cursor的要求,但是如果我們有超過1000的父記錄和超過1500的子(重複條目),那麼這非常慢。所以我想知道是否可以使用CTE而是使用光標來獲得批量插入的性能。

我使用下面的代碼父記錄複製到每個客戶端:

DECLARE @id bigint; 
--Get list of client which will repeat the rows from Master entries 
--This will return three rows Id:1,5,7 
DECLARE client_cursor CURSOR FOR SELECT Id FROM Client WHERE ClientName like 'info%' 
OPEN client_cursor 
    FETCH NEXT FROM client_cursor INTO @id; 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     /*....*/ 
     /* Other business logic performed here */ 
     /*....*/ 
     INSERT INTO Resources (ParentId,ClientId,Location,Title,[Status],Alert) 
     --This will return two rows Id:1,2 
     SELECT Id,@id,Location,Title,[Status],Alert FROM Resources WHERE ParentId IS NULL AND ClientId IS NULL 

     FETCH NEXT FROM client_cursor INTO @id 
    END 
CLOSE client_cursor; 
DEALLOCATE client_cursor; 

以下是之前和使用上面的代碼片斷添加增量家長記錄孩子後的屏幕截圖。 Result of the Query

-- Table Creation 
CREATE TABLE [dbo].[Client](
    [Id] [bigint] IDENTITY(1,1) NOT NULL, 
    [ClientName] [varchar](50) NULL, 
CONSTRAINT [PK_Client] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

CREATE TABLE [dbo].[Resources](
    [Id] [bigint] IDENTITY(1,1) NOT NULL, 
    [ParentId] [bigint] NULL, 
    [ClientId] [bigint] NULL, 
    [Location] [varchar](50) NULL, 
    [Title] [varchar](50) NULL, 
    [Status] [varchar](50) NULL, 
    [Alert] [varchar](50) NULL, 
CONSTRAINT [PK_Resources] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

-- Default Data Insertion 
SET IDENTITY_INSERT [dbo].[Client] ON 
INSERT [dbo].[Client] ([Id], [ClientName]) VALUES (1, N'Infosstretch') 
INSERT [dbo].[Client] ([Id], [ClientName]) VALUES (2, N'Microsoft') 
INSERT [dbo].[Client] ([Id], [ClientName]) VALUES (3, N'Sun System') 
INSERT [dbo].[Client] ([Id], [ClientName]) VALUES (4, N'IBM') 
INSERT [dbo].[Client] ([Id], [ClientName]) VALUES (5, N'Infosys') 
INSERT [dbo].[Client] ([Id], [ClientName]) VALUES (6, N'TCS') 
INSERT [dbo].[Client] ([Id], [ClientName]) VALUES (7, N'Infomatica') 
SET IDENTITY_INSERT [dbo].[Client] OFF 

SET IDENTITY_INSERT [dbo].[Resources] ON 
INSERT [dbo].[Resources] ([Id], [ParentId], [ClientId], [Location], [Title], [Status], [Alert]) VALUES (1, NULL, NULL, N'India', N'Master A', N'New', N'Issue with location') 
INSERT [dbo].[Resources] ([Id], [ParentId], [ClientId], [Location], [Title], [Status], [Alert]) VALUES (2, NULL, NULL, N'Australia', N'Master B', N'Updated', N'No major issue') 
SET IDENTITY_INSERT [dbo].[Resources] OFF 
+1

你爲什麼不嘗試用while循環 – 2017-09-05 10:10:25

+2

這是一個複雜的帖子。如果您想增強某人幫助您的可能性,那麼請考慮添加一個用於創建架構的S​​QL腳本以及您的帖子的示例數據。 –

+0

我也試過用while循環來逐個客戶端進行處理,但是這又會在每個客戶端的數據庫中創建一些讀取操作。我也附上了DB Script如果幫助社區避免從開始寫 – imdadhusen

回答

1

有可能是由您的業務規則的一些原因,是爲簡潔,刪除在這裏,但爲什麼不這樣呢?

INSERT #Resources 
SELECT 
    R.Id AS ParentId, 
    C.Id AS ClientId, 
    R.Location, 
    R.Title, 
    R.Status, 
    R.Alert 
FROM #Resources R 
    CROSS JOIN #Client C 
WHERE R.ParentId IS NULL AND R.ClientId IS NULL -- Root level 
    AND NOT EXISTS (SELECT * FROM #Resources WHERE ParentId = R.Id) -- Not already populated 
    -- AND /* Other business logic performed here */ 
+0

完美答案!正是我正在尋找這個解決方案。能否請您解釋一下爲什麼你已經添加下面的語句'NOT EXISTS(SELECT * FROM #Resources WHERE的ParentId = R.Id)' – imdadhusen

+1

我添加了'這樣萬一這個運行超過一次,它可以確保只有不EXISTS'條款將記錄推送給客戶以獲取尚未推出的資源(避免欺騙)。很高興它適合你! –

+0

非常感謝您的澄清! – imdadhusen

相關問題