4

「Where パラメータをハードコーディングすると tempTable を生成する TADOQuery がありますが、正常に動作しますが、TADO パラメータを使用すると、次のクエリは一時テーブルを認識しません。

私は何を間違っていますか?

この例を簡単にしたいのですが、ここにあります。(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;

コード - 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;
4

1 に答える 1

4

パラメータ化されたクエリはexec sp_executesql、独自のセッションを持つ を使用しています。

これはプロファイラーから取得します。

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

これを SSMS で実行して後で呼び出すとselect * from #ParentChild、同じエラーが発生します。

sp_executesql (Transact-SQL)

sp_executesqlEXECUTEは、バッチ、名前のスコープ、およびデータベース コンテキストに関して同じ動作をします。sp_executesql @stmtパラメーター内の Transact-SQL ステートメントまたはバッチは、sp_executesqlステートメントが実行されるまでコンパイルされません。の内容は@stmt、 を呼び出したバッチの実行計画とは別の実行計画としてコンパイルおよび実行されsp_executesqlます。sp_executesqlバッチは、 を呼び出すバッチで宣言された変数を参照できませんsp_executesql。バッチ内のローカル カーソルまたは変数は、sp_executesqlを呼び出すバッチには表示されませんsp_executesqlsp_executesqlデータベース コンテキストの変更は、ステートメントの最後までしか持続しません。

于 2014-10-24T15:29:50.480 に答える