Da Ihre Daten ein bisschen wie hierarchyId aussehen, habe ich darüber nachgedacht, sie zu verwenden. Die ersten Versionen waren nicht gut auf 1 Million Zeilen skalierbar, jedoch haben einige Indizierungsoptionen in der temporären Haupttabelle geholfen. Probleme können jedoch auch auf meine Testdaten zurückzuführen sein. Können Sie mir also etwas mehr über Ihre Hierarchie erzählen? Zum Beispiel, wie viele Eltern der obersten Ebene gibt es, wie viele Ebenen gibt es durchschnittlich, wie viele Kinder könnte jede Ebene haben?
In der Zwischenzeit finden Sie hier eine Version, damit Sie sie durchsehen und sehen können, ob hierarchyId
sie für Sie funktionieren könnte.
Die Grundidee besteht darin, eine temporäre Tabelle mit den ursprünglichen IDs zu erstellen, in die konvertiert wurde hierarchyIds
, und dann die Hierarchie zu durchlaufen, um die Abstammungslinie zu ermitteln. Diese temporäre Tabelle (die permanent sein könnte) könnte dann für die Migration verwendet werden:
USE tempdb
GO
SET NOCOUNT ON
GO
IF OBJECT_ID('[dbo].[Almoxarifado]') IS NOT NULL DROP TABLE [dbo].[Almoxarifado]
IF OBJECT_ID('[dbo].[Almoxarifado2]') IS NOT NULL DROP TABLE [dbo].[Almoxarifado2]
GO
CREATE TABLE [dbo].[Almoxarifado](
[idAlmoxarifado] [varchar](20) NOT NULL,
[tipoAlmoxarifadoId] [varchar](30) NOT NULL,
[entidadeId] [bigint] NOT NULL,
[dtInclusao] [smalldatetime] NOT NULL,
[dtUltimaAlteracao] [smalldatetime] NULL,
[descricao] [varchar](255) NOT NULL,
[terceiro] [bit] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Almoxarifado2](
[idMaster] [bigint] IDENTITY(1,1) NOT NULL,
[idAlmoxarifado] [int] NOT NULL,
[idAlmoxPai] [int] NOT NULL DEFAULT ((0)),
[entidadeId] [bigint] NOT NULL,
[tipoAlmoxarifadoId] [varchar](30) NOT NULL ,
[dtInclusao] [datetime] NULL DEFAULT (getdate()),
[dtUltimaAlteracao] [datetime] NULL,
[descricao] [varchar](255) NOT NULL,
[terceiro] [bit] NULL DEFAULT ((0)),
PRIMARY KEY ([idMaster])
)
GO
/*
-- Test data
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
VALUES
( '1', 'TESTE', 12, '29 Apr 2016', NULL, '0000000', 0 ),
( '1.1', 'TESTE', 12, '29 Apr 2016', NULL, '0000001', 0 ),
( '1.1.01', 'TESTE', 12, '29 Apr 2016', NULL, '0000002', 0 ),
( '1.1.01.01', 'TESTE', 12, '29 Apr 2016', NULL, '0000003', 0 ),
( '1.1.01.01.001', 'TESTE', 12, '29 Apr 2016', NULL, '0000004', 0 ),
( '1.1.01.01.002', 'TESTE', 12, '29 Apr 2016', NULL, '0000005', 0 ),
( '1.1.01.01.003', 'TESTE', 12, '29 Apr 2016', NULL, '0000006', 0 ),
( '1.1.01.01.004', 'TESTE', 12, '29 Apr 2016', NULL, '0000007', 0 ),
( '1.1.01.01.005', 'TESTE', 12, '29 Apr 2016', NULL, '0000008', 0 ),
( '1.1.01.01.006', 'TESTE', 12, '29 Apr 2016', NULL, '0000009', 0 )
GO
*/
-- Add 10 parent levels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
VALUES
( '1', 'TESTE', 1, '1 Jan 2016', NULL, '00000001', 0 ),
( '2', 'TESTE', 1, '1 Feb 2016', NULL, '00000002', 0 ),
( '3', 'TESTE', 1, '1 Mar 2016', NULL, '00000003', 0 ),
( '4', 'TESTE', 1, '1 Apr 2016', NULL, '00000004', 0 ),
( '5', 'TESTE', 1, '1 May 2016', NULL, '00000005', 0 ),
( '6', 'TESTE', 1, '1 Jun 2016', NULL, '00000006', 0 ),
( '7', 'TESTE', 1, '1 Jul 2016', NULL, '00000007', 0 ),
( '8', 'TESTE', 1, '1 Aug 2016', NULL, '00000008', 0 ),
( '9', 'TESTE', 1, '1 Sep 2016', NULL, '00000008', 0 ),
( '10', 'TESTE', 1, '1 Oct 2016', NULL, '00000010', 0 )
-- For each parent, add 3 sublevels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 5 idAlmoxarifado y FROM [dbo].[Almoxarifado] ) x
-- add n sublevels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.0' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 8 idAlmoxarifado y FROM [dbo].[Almoxarifado] WHERE idAlmoxarifado Not Like '%.%' ) x
WHERE idAlmoxarifado Like '%.%'
-- Add 8 sublevels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.0' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 13 ROW_NUMBER() OVER( ORDER BY idAlmoxarifado ) y FROM [dbo].[Almoxarifado] ) x
WHERE idAlmoxarifado Like '%.%.%'
-- Add 9 sublevels
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.0' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 21 ROW_NUMBER() OVER( ORDER BY idAlmoxarifado ) y FROM [dbo].[Almoxarifado] ) x
WHERE idAlmoxarifado Like '%.%.%.%'
GO
INSERT INTO [dbo].[Almoxarifado] ( idAlmoxarifado, tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro )
SELECT
idAlmoxarifado + '.0' + CAST( x.y AS VARCHAR(10) ),
tipoAlmoxarifadoId, entidadeId, dtInclusao, dtUltimaAlteracao, descricao, terceiro
FROM [dbo].[Almoxarifado] a
CROSS JOIN ( SELECT TOP 9 ROW_NUMBER() OVER( ORDER BY idAlmoxarifado ) y FROM [dbo].[Almoxarifado] ) x
WHERE idAlmoxarifado Like '%.%.%.%.%'
GO
-- Main hierarchyId processing
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL DROP TABLE #tmp
SELECT
IDENTITY( INT, 1, 1 ) AS idMaster,
idAlmoxarifado,
CAST( '/' + REPLACE( REPLACE( REPLACE( idAlmoxarifado, '.0', '.' ), '.0', '.' ), '.', '/' ) + '/' AS hierarchyid ) hId,
CAST( '/' + REPLACE( REPLACE( REPLACE( idAlmoxarifado, '.0', '.' ), '.0', '.' ), '.', '/' ) + '/' AS hierarchyid ).ToString() hString,
CAST( NULL AS INT ) AS idAlmoxarifado2,
CAST( NULL AS INT ) AS idAlmoxPai
INTO #tmp
FROM [dbo].[Almoxarifado]
GO
-- Index temp table to help with recursive CTE
ALTER TABLE #tmp ADD PRIMARY KEY ( idMaster )
ALTER TABLE #tmp ALTER COLUMN hId hierarchyId NOT NULL
CREATE UNIQUE INDEX _idx ON #tmp ( hId ) INCLUDE ( idAlmoxarifado, hString )
GO
-- Walk the hierarchy
;WITH cte AS (
SELECT 1 AS xlevel, idMaster, idAlmoxarifado, hId, hString, hId.GetLevel() getLevel, 0 AS parentId
FROM #tmp
WHERE hId.GetLevel() = 1
UNION ALL
SELECT xlevel + 1, t.idMaster, t.idAlmoxarifado, t.hId, t.hString, t.hId.GetLevel() getLevel, c.idMaster AS parentId
FROM cte c
INNER JOIN #tmp t ON c.hId = t.hId.GetAncestor(1)
)
UPDATE t
SET
-- Parse out the individual node, by taking its parent and stuffing it in front
t.idAlmoxarifado2 = CAST( REPLACE( STUFF( c.hString, 1, LEN(c.hId.GetAncestor(1).ToString()), '' ), '/', '' ) AS INT ),
t.idAlmoxPai = parentId
FROM cte c
INNER JOIN #tmp t ON c.idMaster = T.idMaster
-- Check results
SELECT *
FROM #tmp
Dieses gesamte Skript (einschließlich der Erstellung von Testdaten) läuft auf meinem Laptop in nur wenigen Minuten.