2016-12-01 1 views
0

200M 개 이상의 레코드를로드해야하는 동적 SQL 쿼리를 실행하려고합니다. 한 번에 모든 레코드를로드하려고했지만 'System.OutOfMemory'예외가 생겼으므로 시간 간격을 개월로 나누기로 결정했습니다. 단 한 달 동안 실행하더라도 다음 시간은 1 시간 이상 실행됩니다. 나는 날짜를 하드 코딩하고 'While'없이 실행했고 정상적으로 실행됩니다. 어떤 오류가 있는지 누군가 확인하고 알려 줄 수 있습니까? 다음은동적 SQL 실행 속도가 너무 깁니 다

DECLARE @FromDate VARCHAR(MAX)='', 
     @params nvarchar(max) = N'@StartDate Date out,@EndDate Date out,@FromDate date out,@ToDate date out', 
     @SQL NVARCHAR(MAX)=’’, 
     @ToDate VARCHAR(MAX)='', 
     @StartDate VARCHAR(MAX)=’’, 
     @EndDate VARCHAR(MAX)=’’; 

SELECT @FromDate= DATEADD(DAY,-365, GETUTCDATE()), @ToDate =  GETUTCDATE(); 
SELECT @[email protected], @EndDate=CAST(DATEADD(MONTH,1, @FromDate) AS DATE); 
SET @SQL = ' 
WHILE ''' + @FromDate + ''' < ''' + @ToDate + ''' 
    BEGIN 
    INSERT INTO dbo.Sales 
    (
    ProductID, 
    SaleDate, 
    Quantity 
    ) 
Select 
     ProductID, 
     SaleDate, 
     Quantity 
from 
    OPENQUERY(TeraData1,'' 
     Select 
     PR_ID   AS ProductID, 
     SL_Date   AS SaleDate, 
     PR_QTY   AS Quantity 
    FROM 
     Sales.Product 
    where 
SaleDate BETWEEN ' + @StartDate + 'AND '+ @EndDate + ' 
'') 

SET @FromDate =DATEADD(MONTH,1,'''+ @FromDate +''') 
SET @StartDate =DATEADD(MONTH,1,'''+ @StartDate +''') 
SET @EndDate =DATEADD(MONTH,1,'''+ @EndDate +''') 
END’ 

EXECUTE sp_executesql @SQL, @params, 
       @[email protected], 
       @[email protected], 
       @StartDate = @StartDate out, 
       @EndDate = @EndDate out; 
+1

왜 저장 사용하지 프로 시저/함수 논리 대신 동적 SQL :

이 동적으로 비 동적 SQL에서 제어 흐름을 유지하고 여기에 매개 변수를 전달하고 싶은 경우는 예입니다? –

+1

@ TonyDong은 동적 SQL을 필요로하는 구문을 사용하고있는 구문에는 아무 것도 없습니다. 정규 WHILE 제어 구문을 사용할 수 있습니다. 그리고 약간의 어려움이 있지만 likely 문제는 무엇입니까? 동적 SQL과 컨트롤 흐름 사이에서 변수의 범위를 혼합하는 것입니다. – Matt

+1

그리고 문제의 일부가 될 수도있는 데이터 유형을 일부 혼합하고 있습니다. – Matt

답변

2
DECLARE @FromDate DATE 

SET @FromDate = DATEADD(YEAR,-1,GETUTCDATE()) 

WHILE @FromDate < GETUTCDATE() 
BEGIN 
    INSERT INTO dbo.Sales 
    (
     ProductID, 
     SaleDate, 
     Quantity 
    ) 
Select 
     ProductID, 
     SaleDate, 
     Quantity 
from 
    OPENQUERY(TeraData1, 
     Select 
      PR_ID   AS ProductID, 
      SL_Date   AS SaleDate, 
      PR_QTY   AS Quantity 
     FROM 
      Sales.Product 
     where 
      SaleDate >= @FromDate AND SaleDate < DATEADD(MONTH,1,@FromDate) 
    ) 

    SET @FromDate =DATEADD(MONTH,1,@FromDate) 
END 

그것은 당신이/당신이 필요로하는 것보다 날짜를 방법 이상의 변수를 가지고있는 것처럼 당신이 연결된 서버 이름 또는 다른 전달하고자하지 않는 동적 SQL을 필요로하지 않는 것이 보이는 내 쿼리입니다 동적으로 열.

SQL이 원하는 값을 유추하는 대신 매개 변수에 적절한 데이터 유형을 사용하십시오.

또한 날짜의 BETWEEN을 사용하면 비교의 한도를 수정하는 것이 포함되므로 특정 날짜가 중복됩니다.

DECLARE @FromDate DATE 

SET @FromDate = DATEADD(YEAR,-1,GETUTCDATE()) 

WHILE @FromDate < GETUTCDATE() 
BEGIN 

    DECLARE @LinkedServerName NVARCHAR(MAX) = 'TeraData1' 
    DECLARE @ParamDef NVARCHAR(MAX) = '@FromDate DATE' 
    DECLARE @SQL NVARCHAR(MAX) 

    SET @SQL = ' 
     INSERT INTO dbo.Sales 
     (
     ProductID, 
     SaleDate, 
     Quantity 
    ) 
    Select 
     ProductID, 
     SaleDate, 
     Quantity 
    from 
     OPENQUERY(' + @LinkedServerName + ', 
      Select 
      PR_ID   AS ProductID, 
      SL_Date   AS SaleDate, 
      PR_QTY   AS Quantity 
      FROM 
      Sales.Product 
      where 
      SaleDate >= @FromDate AND SaleDate < DATEADD(MONTH,1,@FromDate) 
     )' 

    EXECUTE sp_executesql @SQL, @PramDef, @FromDate = @FromDate 

    SET @FromDate =DATEADD(MONTH,1,@FromDate) 
END 
관련 문제