本帖最后由 goodhj 于 2010-07-08 09:09:50 编辑

解决方案 »

  1.   

    搜到的答案:Delphi(Pascal) code    DBConsts_SExprBadScope, "Operation cannot mix aggregate value with record-varying value"以上是google搜索到的结果,用关键字“SExprBadScope”查询delphi7的VCL源代码得到以下2条提示:Delphi(Pascal) code    Build Search for 'SExprBadScope' D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1878): DatabaseError(SExprBadScope); D:\Program Files\Borland\Delphi7\Source\Vcl\DBConsts.pas(72): SExprBadScope = 'Operation cannot mix aggregate value with record-varying value';进入以上2个查询结果的vcl源代码文件位置查看,是Delphi(Pascal) code    procedure TExprParser.GetScopeKind(Root, Left, Right : PExprNode);内抛出此异常,再用TExprParser关键字查vcl源代码的到以下结果:Delphi(Pascal) code    Build Search for 'TExprParser' D:\Program Files\Borland\Delphi7\Source\Vcl\DBClient.pas(3811): with TExprParser.Create(Self, Expr, Options, [poExtSyntax], '', nil, FieldTypeMap) do D:\Program Files\Borland\Delphi7\Source\Vcl\DBClient.pas(3996): ExprParser: TExprParser; D:\Program Files\Borland\Delphi7\Source\Vcl\DBClient.pas(4037): ExprParser := TExprParser.Create(Self, Expr, FilterOptions, [], '', nil, FieldTypeMap); D:\Program Files\Borland\Delphi7\Source\Vcl\DBClient.pas(4573): procedure AddSQLExprAttr(ExprParser: TExprParser; const ExprText, ExprErrMsg, D:\Program Files\Borland\Delphi7\Source\Vcl\DBClient.pas(4632): ExprParser: TExprParser; D:\Program Files\Borland\Delphi7\Source\Vcl\DBClient.pas(4635): ExprParser := TExprParser.Create(Self, '', [], [], '', nil, FieldTypeMap); D:\Program Files\Borland\Delphi7\Source\Vcl\DBClient.pas(4859): Parser: TExprParser; D:\Program Files\Borland\Delphi7\Source\Vcl\DBClient.pas(4873): Parser := TExprParser.Create(FDataSet, FExpression, [], D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(164): { TExprParser } D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(170): TExprParser = class D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1298): constructor TExprParser.Create(DataSet: TDataSet; const Text: string; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1314): destructor TExprParser.Destroy; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1319): procedure TExprParser.SetExprParams(const Text: string; Options: TFilterOptions; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1362): function TExprParser.NextTokenIsLParen : Boolean; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1393): procedure TExprParser.NextToken; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1605): function TExprParser.ParseExpr: PExprNode; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1618): function TExprParser.ParseExpr2: PExprNode; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1631): function TExprParser.ParseExpr3: PExprNode; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1645): function TExprParser.ParseExpr4: PExprNode; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1741): function TExprParser.ParseExpr5: PExprNode; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1764): function TExprParser.ParseExpr6: PExprNode; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1788): function TExprParser.ParseExpr7: PExprNode; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1868): procedure TExprParser.GetScopeKind(Root, Left, Right : PExprNode); D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1887): procedure TExprParser.GetFuncResultInfo(Node : PExprNode); D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1942): function TExprParser.TokenName: string; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1951): function TExprParser.TokenSymbolIs(const S: string): Boolean; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1957): function TExprParser.TokenSymbolIsFunc(const S: string) : Boolean; D:\Program Files\Borland\Delphi7\Source\Vcl\DBCommon.pas(1982): procedure TExprParser.TypeCheckArithOp(Node: PExprNode); D:\Program Files\Borland\Delphi7\Source\Vcl\DBTables.pas(5328): Parser: TExprParser; D:\Program Files\Borland\Delphi7\Source\Vcl\DBTables.pas(5330): Parser := TExprParser.Create(Self, Expr, Options, [], '', nil, FldTypeMap); D:\Program Files\Borland\Delphi7\Source\Vcl\Provider.pas(1285): procedure AddSQLExprAttr(ExprParser: TExprParser; const ExprText, ExprErrMsg, D:\Program Files\Borland\Delphi7\Source\Vcl\Provider.pas(1338): ExprParser: TExprParser; D:\Program Files\Borland\Delphi7\Source\Vcl\Provider.pas(1343): ExprParser := TExprParser.Create(DataSet, '', [], [], '', nil, FieldTypeMap);跟踪各个源文件,应该是数据库操作方面的问题
      

  2.   

    原帖地址:http://topic.csdn.net/u/20090704/21/9e065d51-4c76-4f50-9233-73695be7b182.html
      

  3.   

    是在两个板块里开的帖子,呵呵。撒大网嘛Avan_Lau:完全说是代码问题可能不好解释,因为是不定时的,而且不是经常的。报这个错误是在一个模块关闭刚刚进入另外一个模块后,进入时会做一些下拉框值填充,用的是DBClient的CommandText执行了聚合语句。但是DBClient每执行一个CommandText前都用了Close的,应该是没问题的呀
    还有一个现象啊,虽然会报这个错,点掉继续用是没有任何问题的,并不影响系统的任何使用。
      

  4.   

    查这类不可重现的错误,建议先把代码中的哪些编译告警、提示处理一下。以往痛苦经验,一个不可重现错误,查来查去最后发现是函数返回值没有初始化,返回垃圾值,而这类问题DELPHI是有编译告警的。
      

  5.   

    编译告警、提示一个也没有,我也是很注意这方面问题的,呵呵刚刚抓到了,报错时停留在DB.Pas里
    procedure DatabaseError(const Message: string; Component: TComponent = nil);
    begin
      if Assigned(Component) and (Component.Name <> '') then
        raise EDatabaseError.Create(Format('%s: %s', [Component.Name, Message])) else
        raise EDatabaseError.Create(Message);
    end;
    光标停留在raise EDatabaseError.Create(Message);这句
    所以应该是raise EDatabaseError.Create(Format('%s: %s', [Component.Name, Message])) 这句出的operation cannot mix aggregate value with record-varying value 这个错误信息,但是没有错误信息里没有Component.Name呢???
      

  6.   

    发生这种现象是这样发生的,
    客户端我都用的TClientDataSet,服务端用的TADOQuery+TDataSetProvider,设置TDataSetProvider的[poAllowCommandText]为True来执行客户端TClientDataSet提交的CommandText;
    TADOTable+TDataSetProvider来给客户端的TClientDataSet直接访问表;我从初始用到聚合语句的模块到一个初始没用聚合语句但要打开表的模块时,偶尔就会出现这个错误,出了这个错想进的模块就不能动态生成了,要把错误点掉后在进模块就可以了
      

  7.   

    我在DBConsts中找到这个错误了SExprBadScope = 'Operation cannot mix aggregate value with record-varying value',然后搜索了找到了代码行:procedure  TExprParser.GetScopeKind(Root, Left, Right : PExprNode);
    begin
      if (Left = nil) and (Right = nil) then Exit;
      if Right = nil then
      begin
        Root.FScopeKind := Left.FScopeKind;
        Exit;
      end;
      if ((Left^.FScopeKind = skField) and (Right^.FScopeKind = skAgg))
         or ((Left^.FScopeKind = skAgg) and (Right^.FScopeKind = skField)) then
        DatabaseError(SExprBadScope);
      if (Left^.FScopeKind = skConst) and (Right^.FScopeKind = skConst) then
        Root^.FScopeKind := skConst
      else if (Left^.FScopeKind = skAgg) or (Right^.FScopeKind = skAgg) then
        Root^.FScopeKind := skAgg
      else if (Left^.FScopeKind = skField) or (Right^.FScopeKind = skField) then
        Root^.FScopeKind := skField;
    end;希望对你有用。
      

  8.   

    我也跟踪过,就是跟踪TCustomClientDataSet的Open过程要执行哪些动作,跟到后面跟丢了,因为执行的动作太多,也不在同一个Unit里,倒过去跟TExprParser更不可能,太多地方用,头都大了,最后放弃跟踪执行Open过程要执行的动作了。因为在做试验的时候偶然把问题解决掉了,运气比较好哈,呵呵,但不知道原因是什么,贴出来请大家分析下,明天结帖
      var
      ProduceOP:String;
     begin
      ......
      ProduceOP:=GetProduceOP;//GetProduceOP是一个获取字符串的函数,得到的是类似''123'',''234'',''345''的字符串
      CDS_Produce.Filtered:=False;
      CDS_Produce.Filter:='OP_Code in('+ProduceOP+') and Flag=''Begin''';  
      CDS_Produce.Filtered:=True;
      CDS_Produce.Open;
      .....
     end;
    这样就不会不定时跳那错出来,但是下面这种写法就会偶尔的,不定时的跳operation cannot mix aggregate value with record-varying value 这个错误,
    var
      ProduceOP:String;
     begin
      ......
      ProduceOP:=GetProduceOP;//GetProduceOP是一个获取字符串的函数,得到的是类似''123'',''234'',''345''的字符串
      CDS_Produce.Filtered:=False;
      CDS_Produce.Filter:='(Not OP_Code in('+ProduceOP+')) and Flag=''Begin''';  
      CDS_Produce.Filtered:=True;
      CDS_Produce.Open;
      .....
     end;
    本来想少写一个函数省点事情,但是没有省着。各位兄弟有什么看法?
      

  9.   

    CDS_Produce 是TClientDataSet,对应着服务器端的TAdoTable;GetProduceOP函数里用的是另外一个
    TClientDataSet,对应着服务器端的TAdoQuery
      

  10.   

    一个是IN,CDS_Produce.Filter:='OP_Code in('+ProduceOP+') and Flag=''Begin''';   
    一个是NOT,CDS_Produce.Filter:='(Not OP_Code in('+ProduceOP+')) and Flag=''Begin''';逻辑对吗?
      

  11.   

    逻辑是没问题的,就是为了少写一个函数才用到NOT的
      

  12.   

    我实际代码用 OP_Code in('+EngineerOP+')来代替Not OP_Code in('+ProduceOP+') 也就是另外写了一个函数来实现我要的过滤条件,不让in条件前出现Not,就不出现我说的问题了。
    我是偶然看到我另外一个模块进去打开表的过滤条件in条件前没有not,我就不停的进入那个模块,发现点了好几分钟,估计有好几百次,都没出那错误,而进入过滤条件in条件前有not的那个模块,基本上点个两分钟左右,过滤的结果虽然正确,但估计一百次左右的时候就会跳错。
    我这笨人啊没办法就不停的点啊点来验证,
    大家有什么看法吗?虽然幸运的解决了问题但是不知道原因总是有点遗憾啊
      

  13.   

    过滤的话,数据集不需要反复close,open。另外,你在客户端发送commandtext,返回的数据结构有没有可能跟之前取的结构有变化?从错误讯息看,可能是因为结构发生变化,聚集字段对应的类型不符合造成...
      

  14.   

    没有反复close,open。
    CDS_Produce 是TClientDataSet,对应着服务器端的TAdoTable;没有用CommandText;直接用的Filter 来设置的过滤条件,可能是过滤条件中的in条件前面不能有NOT。Filter还是比不得CommandText可以执行真正的Sql语句,估计TClientDataSet在使过滤条件起作用的时候出问题了(我猜测的),但是解释不了为什么有Not结果是正确的,只是会不知道哪一次打开的时候就会报错operation cannot mix aggregate value with record-varying value.
      

  15.   

    问题发生的不确定 + filter条件in/not效果不同说明,过滤后的结果不同,从而触发聚集字段结果也不同,有的会出现此错误,有的没出现此错误。所以问题,并不在filter是否用not。而是在于你的数据内容。假设你不用not,内容跟用not是一样的,那么错误还是会出现。最根本的是检查你的聚集字段要处理的是哪种数据类型,对比实际的数据内容,会碰到怎样的状况?!
      

  16.   

    是字符类型的,可能我没描述太清楚,举个例子。比如我OP_Code 总共有'123','234','345','456'
    现在我要设置过滤条件:OP_Code in('123','234')
    这个过滤条件与Not OP_Code in('345','456')这个过滤条件执行的结果是一样的,也是我想要的结果,但是用Not OP_Code in('345','456')这个过滤条件就会出现我提的问题。
      

  17.   

    你没理解我的意思并不是指OP_Code 内容,而是数据集里面的其它内容。你的代码,你应该自己最清楚。在数据打开或执行过滤后,触发了什么事件,这些事件对数据内容是否做了什么处理...
      

  18.   

    CDS_Produce.Filtered:=False;
      CDS_Produce.Filter:='(Not  OP_Code in('+ProduceOP+')) and Flag=''Begin''';   //换成OP_Code not in(....)试试
      CDS_Produce.Filtered:=True;
      CDS_Produce.Open;