2014-02-24 4 views
3

파일이 비정규 화되어 있습니다. 좋은 이유 때문에, 나는 이것을 바꿀 수 없다. LightSwitch에서 사용하기 위해 정규화 된 관련 테이블로 가져와야합니다. 데이터에는 원래 테이블에 대한 ID 컬럼 값이 들어 있지 않습니다. 저는 4 개의 컬럼을 가지고 있습니다 :가져 오기에서 데이터를 효율적으로 정규화하는 방법은 무엇입니까?

Division Branch Position Location 

정규화 된 데이터의 스키마는 다음과 같습니다. Division은 Branches를 포함합니다. 지점에는 위치가 포함됩니다. 위치 및 위치는 PositionLocationMappings 테이블을 통해 다 대다 관계를 갖습니다.

테이블에 비정규 화 된 데이터를 가져 오기 위해 BULK INSERT를 수행합니다. 그런 다음 행별로 처리하여 각 행에 대해 저장 프로 시저를 호출합니다. 원본 파일에는 약 16,000 개의 행이 있으며 27 초가 소요됩니다. 다소 느린 것 같습니다. 더 빨리 할 수있는 방법이 있습니까? 여기에 저장된 프로 시저 것

DECLARE @division nvarchar(240) 
DECLARE @branch nvarchar(240) 
DECLARE @position nvarchar(240) 
DECLARE @location nvarchar(60) 

DECLARE myCursor CURSOR LOCAL FOR 
    SELECT DISTINCT Division,Branch,Position,Location 
     FROM [staging].BranchPositions 

OPEN myCursor 

FETCH NEXT FROM myCursor INTO @division, @branch, @position, @location 

WHILE @@FETCH_STATUS = 0 BEGIN 
    EXECUTE [dbo].[usp_InsertBranchPositions] @division,@branch,@position,@location 

    FETCH NEXT FROM myCursor INTO @division, @branch, @position, @location 
END 

CLOSE myCursor 
DEALLOCATE myCursor 

을 그리고 : 세트 -와

ALTER PROCEDURE [dbo].[usp_InsertBranchPositions] 
    @division nvarchar(240), 
    @branch nvarchar(240), 
    @position nvarchar(240), 
    @location nvarchar(60) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    BEGIN TRANSACTION 

    DECLARE @divisionTable TABLE (InsertedDivisionId int) 
    DECLARE @branchTable TABLE (InsertedBranchId int) 
    DECLARE @positionTable TABLE (InsertedPositionId int) 
    DECLARE @locationTable TABLE (InsertedLocationid int) 

    DECLARE @divisionId int 
    DECLARE @branchId int 
    DECLARE @positionId int 
    DECLARE @locationId int 

    SELECT @divisionId = [Id] FROM [dbo].[Divisions] 
    WHERE DivisionName = @division 

    IF @divisionId IS NULL 
    BEGIN 
     INSERT INTO [dbo].[Divisions] (DivisionName, IsDivisionActive) 
      VALUES (@division, 1) 
     SELECT @divisionId = SCOPE_IDENTITY() 
    END 

    SELECT @branchId = [Id] FROM [dbo].[Branches] 
    WHERE BranchName = @branch 

    IF @branchId IS NULL 
    BEGIN 
     INSERT INTO [dbo].[Branches] (BranchName, IsBranchActive, DivisionId) 
      VALUES (@branch, 1, @divisionId) 
     SELECT @branchId = SCOPE_IDENTITY() 
    END 

    SELECT @positionId = [Id] FROM [dbo].[Positions] 
    WHERE PositionName = @position 

    IF @positionId IS NULL 
    BEGIN 
     INSERT INTO [dbo].[Positions] (PositionName, IsPositionActive, BranchId) 
      VALUES (@position, 1, @branchId) 
     SELECT @positionId = SCOPE_IDENTITY() 
    END 

    SELECT @locationId = [Id] FROM [dbo].[Locations] 
    WHERE LocationName = @location 

    IF @locationId IS NULL 
    BEGIN 
     INSERT INTO [dbo].[Locations] (LocationName, IsLocationActive) 
      VALUES (@location, 1) 
     SELECT @locationId = SCOPE_IDENTITY() 
    END 

    INSERT INTO [dbo].[PositionLocationMappings] (PositionId, LocationId) 
     VALUES (@positionId, @locationId) 

    COMMIT TRANSACTION 
END 

답변

2

각 행에 대한 프로 시저를 호출 가져올 수있는 대신에 데이터

이 내 PostDeployment.sql 스크립트에 기반 작업.

IF @divisionId IS NULL 
BEGIN 
    INSERT INTO [dbo].[Divisions] (DivisionName, IsDivisionActive) 
     VALUES (@division, 1) 
    SELECT @divisionId = SCOPE_IDENTITY() 
END 

하려면 :

예를 들어,이 조각에 의해 수행 된 작업 변경할 수 있습니다 Branches에 대한

insert Divisions 
     (DivisionName, IsDivisionActive) 
select distinct DivisionName 
,  1 
from BranchPositions 

다음을, 당신은 DivisionId을 찾기 위해 join을 사용 :

insert Branches 
     (BranchName, IsBranchActive, DivisionId) 
select distinct BranchName 
,  1 
,  d.Id 
from BranchPositions bp 
join Divisions d 
on  bp.DivisionName = d.DivisionName 

등등. 그 속도가 훨씬 빨라야합니다. 저는 수십억 개의 행을 1 분 이내에 가져 오기 위해 사용했습니다.

+0

SQL에서 항상 IF 문과 커서를 제거하면 쿼리 속도가 향상됩니다 – Hogan

+0

감사합니다. 이제는 1 초 안에 실행됩니다. – user2871239

관련 문제