刚刚抓到了,报错时停留在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呢???发生这种现象是这样发生的, 客户端我都用的TClientDataSet,服务端用的TADOQuery+TDataSetProvider,设置TDataSetProvider的[poAllowCommandText]为True来执行客户端TClientDataSet提交的CommandText; TADOTable+TDataSetProvider来给客户端的TClientDataSet直接访问表;我从初始用到聚合语句的模块到一个初始没用聚合语句但要打开表的模块时,偶尔就会出现这个错误,出了这个错想进的模块就不能动态生成了,要把错误点掉后在进模块就可以了
我在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; 希望对你有用。
我也跟踪过,就是跟踪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; 本来想少写一个函数省点事情,但是没有省着。各位兄弟有什么看法?
一个是IN,CDS_Produce.Filter:='OP_Code in('+ProduceOP+') and Flag=''Begin'''; 一个是NOT,CDS_Produce.Filter:='(Not OP_Code in('+ProduceOP+')) and Flag=''Begin''';逻辑对吗?
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';procedure TExprParser.GetScopeKind(Root, Left, Right : PExprNode);内抛出此异常,再用TExprParser关键字查vcl源代码的到以下结果: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);跟踪各个源文件,应该是数据库操作方面的问题仅供给楼主参考,如无可取,可忽略这个回复。
还有一个现象啊,虽然会报这个错,点掉继续用是没有任何问题的,并不影响系统的任何使用。
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呢???发生这种现象是这样发生的,
客户端我都用的TClientDataSet,服务端用的TADOQuery+TDataSetProvider,设置TDataSetProvider的[poAllowCommandText]为True来执行客户端TClientDataSet提交的CommandText;
TADOTable+TDataSetProvider来给客户端的TClientDataSet直接访问表;我从初始用到聚合语句的模块到一个初始没用聚合语句但要打开表的模块时,偶尔就会出现这个错误,出了这个错想进的模块就不能动态生成了,要把错误点掉后在进模块就可以了
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;
希望对你有用。
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;
本来想少写一个函数省点事情,但是没有省着。各位兄弟有什么看法?
TClientDataSet,对应着服务器端的TAdoQuery
一个是NOT,CDS_Produce.Filter:='(Not OP_Code in('+ProduceOP+')) and Flag=''Begin''';逻辑对吗?
我是偶然看到我另外一个模块进去打开表的过滤条件in条件前没有not,我就不停的进入那个模块,发现点了好几分钟,估计有好几百次,都没出那错误,而进入过滤条件in条件前有not的那个模块,基本上点个两分钟左右,过滤的结果虽然正确,但估计一百次左右的时候就会跳错。
我这笨人啊没办法就不停的点啊点来验证,
大家有什么看法吗?虽然幸运的解决了问题但是不知道原因总是有点遗憾啊
CDS_Produce 是TClientDataSet,对应着服务器端的TAdoTable;没有用CommandText;直接用的Filter 来设置的过滤条件,可能是过滤条件中的in条件前面不能有NOT。Filter还是比不得CommandText可以执行真正的Sql语句,估计TClientDataSet在使过滤条件起作用的时候出问题了(我猜测的),但是解释不了为什么有Not结果是正确的,只是会不知道哪一次打开的时候就会报错operation cannot mix aggregate value with record-varying value.
现在我要设置过滤条件:OP_Code in('123','234')
这个过滤条件与Not OP_Code in('345','456')这个过滤条件执行的结果是一样的,也是我想要的结果,但是用Not OP_Code in('345','456')这个过滤条件就会出现我提的问题。