TADOQuery临时表如果在查询中有参数,则丢失

时间:2014-10-24 15:08:10

标签: sql-server delphi temp-tables tadoquery

我有一个生成tempTable的TADOQuery,如果我硬编码“Where参数,它工作正常,但如果我使用TADO参数,下一个查询不知道临时表。

我做错了什么?

我希望我可以简化这个例子但是在这里。 (SQL Server)

    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;

1 个答案:

答案 0 :(得分: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 sp_executesql参数中的Transact-SQL语句或批处理。然后将@stmt的内容编译并执行为与调用sp_executesql的批处理的执行计划分开的执行计划。 sp_executesql批处理不能引用调用sp_executesql的批处理中声明的变量。 sp_executesql批处理中的本地游标或变量对于调用sp_executesql的批处理不可见。数据库上下文的更改仅持续到sp_executesql语句的末尾。