2014-10-24 11 views
3

"Where 매개 변수를 하드 코딩하면 TADOQuery가 생성되지만 TADO 매개 변수를 사용하면 다음 쿼리에 대해 알 수 없습니다. 임시 테이블.TADOQuery 임시 테이블 쿼리에 매개 변수가있는 경우 손실된다

내가 잘못 뭐하는 거지?

내가이 예를 단순화 할 수 싶지만 여기있다. (SQL 서버)

CREATE TABLE brFTNode_Children ( 
     pID integer NOT NULL, 
     cID integer NOT NULL, 
     primary key (pID, cID) 
    ); 

    insert into brFTNode_Children values(1,2); 
    insert into brFTNode_Children values(1,3); 
    insert into brFTNode_Children values(3,4); 
    insert into brFTNode_Children values(3,5); 
    insert into brFTNode_Children values(6,4); 
    insert into brFTNode_Children values(6,7); 

코드 (작동하지 않습니다)

procedure Foo(fDBCon : TADOConnection); 
const 
    CreateTempTable = 
        'WITH FT_CTE AS(' + 
        'SELECT pID, cID FROM brFTNode_Children ' + 
        'WHERE pID = :TOPID ' + 
        'UNION ALL ' + 
        ' SELECT e.pID, e.cID FROM brFTNode_Children e ' + 
        ' INNER JOIN FT_CTE ftCTE on (ftCTE.cID = e.pID)) ' + 
        'SELECT * INTO #ParentChild FROM FT_CTE; '; 


    GetSQL = 
        'SELECT pID, cID FROM #ParentChild ORDER BY pID; '; 
var 
    q1 : TADOQuery; 
    q2 : TADOQuery; 

begin 
    q1 := TADOQuery.Create(nil); 
    q1.Connection := fDBCon; 
    q1.SQL.Text := CreateTempTable; 
    q1.ParamCheck := True; 
    q1.Parameters.ParamByName('TOPID').DataType := ftInteger; 
    q1.Parameters.ParamByName('TOPID').Value := 1; 
    q1.ExecSQL; 

    q2 := TADOQuery.Create(nil); 
    q2.Connection := fDBCon; 
    q2.SQL.Text := GetSQL; 
    q2.Active := true; //Fails here does not know table #ParentChild 
end; 

코드 - 그것의 자신의 세션을 가진 매개 변수가있는 쿼리가 exec sp_executesql를 사용하는 SQL 쿼리

function TGenerateSolveFile.GetBinaryStream( topID : Cardinal; 
              var bFile: TMemoryStream): Boolean; 

const 
    CreateTempTable = 
        'WITH FT_CTE AS(' + 
        'SELECT pID, cID FROM brFTNode_Children ' + 
        'WHERE pID = 1 ' + //Changed To a constant 
        'UNION ALL ' + 
        ' SELECT e.pID, e.cID FROM brFTNode_Children e ' + 
        ' INNER JOIN FT_CTE ftCTE on (ftCTE.cID = e.pID)) ' + 
        'SELECT * INTO #ParentChild FROM FT_CTE; '; 


    GetSQL = 
        'SELECT pID, cID FROM #ParentChild ORDER BY pID; '; 
var 
    q1 : TADOQuery; 
    q2 : TADOQuery; 

begin 
    q1 := TADOQuery.Create(nil); 
    q1.Connection := fDBCon; 
    q1.SQL.Text := CreateTempTable; 
// q1.ParamCheck := True; 
// q1.Parameters.ParamByName('TOPID').DataType := ftInteger; 
// q1.Parameters.ParamByName('TOPID').Value := 1; 
    q1.ExecSQL; 

    q2 := TADOQuery.Create(nil); 
    q2.Connection := fDBCon; 
    q2.SQL.Text := GetSQL; 
    q2.Active := true; 
end; 
+1

왜 2 개의 쿼리를 실행해야합니까? 당신은 단순히'q2.SQL.Text : = CreateTempTable + GetSQL; '을 시도해 보았습니다. 어떤 경우이든 하나의 SP를 만들 것입니다. 매개 변수를 전달하고 레코드 세트를 다시 가져옵니다. – kobik

답변

3

에 일정한 작동합니다.

프로파일 러에서 얻을 수 있습니다. 당신이 SSMS에서 이것을 실행하고 select * from #ParentChild를 호출하는 경우

exec sp_executesql N'WITH FT_CTE AS(SELECT pID, cID FROM brFTNode_Children WHERE pID = @P1 UNION ALL SELECT e.pID, e.cID FROM brFTNode_Children e INNER JOIN FT_CTE ftCTE on (ftCTE.cID = e.pID)) SELECT * INTO #ParentChild FROM FT_CTE; 
',N'@P1 int',1 

나중에 동일한 오류가 발생합니다.

sp_executesql

sp_executesql (Transact-SQL)

일괄 처리에 대해서는, 이름의 범위 및 데이터베이스 컨텍스트 EXECUTE 같은 문제가있다. sp_executesql @stmt 매개 변수의 Transact-SQL 문 또는 일괄 처리는 sp_executesql 문을 실행할 때까지 컴파일되지 않습니다. @stmt의 내용은 sp_executesql을 호출 한 일괄 처리의 실행 계획과는 별도로 실행 계획으로 컴파일되어 실행됩니다. sp_executesql 일괄 처리는 sp_executesql을 호출하는 일괄 처리에서 선언 된 변수를 참조 할 수 없습니다. sp_executesql 일괄 처리의 로컬 커서 또는 변수는 sp_executesql이라는 일괄 처리에 표시되지 않습니다. 데이터베이스 컨텍스트의 변경은 sp_executesql 문 끝까지입니다.

+0

다른 쿼리가 동일한 세션을 사용하는 방법이 있습니까? 나는 그것을 필요로하는 각 쿼리에 대해 임시 쿼리를 실행하지 않아도되고 동일한 코드를 수행하는 여러 스레드가 있기 때문에 실제 테이블을 만들 수 없습니다. 아니면 다른 해결책이 있습니다. – runfastman

+0

sp_executesql이 끝난 후 세션이 손실되면 다른 사용자와의 충돌을 피하기 위해 이름이 적용된 GUID로 구성된 전역 임시 테이블을 사용할 수 있습니다. 이러한 사용자는 마지막 사용자의 연결이 끊어진 후에 삭제됩니다. ## F7BBE50B_9406_4A35_9FAD_6C54D317A390과 같은 것입니다. 좋은 질문 : 좋은 준비. :) – bummi

+0

나는 해결책을 발견했고, 조금 양떼를 느낀다. 쿼리를 실행하기 전에 문자열의 ID를 바꿉니다. 간단한 솔루션. – runfastman