TADOQuery Temp Table Lost if it has a parameter in query

我是研究僧i 提交于 2019-12-10 17:18:00

问题


I have a TADOQuery that generates a tempTable if I hard code the "Where parameter, it works fine, but if I use a TADO Parameter the next query doesn't know about the temp table.

What am I doing wrong?

I wish I could simplify this example but here it is. (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);

Code (Doesn't work)

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;

Code - Works with the constant in the SQL query

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:


A parameterized query is using exec sp_executesql, which has it's own session.

You will get this from the profiler.

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

If you execute this in the SSMS and call select * from #ParentChild afterwards you will get the same error.

sp_executesql (Transact-SQL)

sp_executesql has the same behavior as EXECUTE with regard to batches, the scope of names, and database context. The Transact-SQL statement or batch in the sp_executesql @stmt parameter is not compiled until the sp_executesql statement is executed. The contents of @stmt are then compiled and executed as an execution plan separate from the execution plan of the batch that called sp_executesql. The sp_executesql batch cannot reference variables declared in the batch that calls sp_executesql. Local cursors or variables in the sp_executesql batch are not visible to the batch that calls sp_executesql. Changes in database context last only to the end of the sp_executesql statement.



来源:https://stackoverflow.com/questions/26550791/tadoquery-temp-table-lost-if-it-has-a-parameter-in-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!