ADO中的#个标志位于(Delphi XE5)

时间:2015-09-24 01:15:38

标签: delphi ado

使用TADOQuery.Locate使用字段列表和VarArray值,如果其中一个值包含#符号,我们会得到以下异常:

'Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.'

我已将其追溯到ADODB,ADODB本身似乎使用#符号作为分隔符。

有没有办法逃脱#-signs以便查询不会失败?

*编辑1 *

我错了。导致此失败的原因是一个字符串,其单符号为。下面显示的代码失败,上面提到了错误消息。

真正让我们担心的是,当它在IDE外部以.exe运行失败时,没有运行时异常。我们只在IDE中看到异常。如果我们的程序员没有碰巧使用触发此操作的数据,我们就不会知道.Locate由于运行时错误而返回FALSE,而不是因为找不到匹配的记录。

代码:

var 
  SearchArray: Variant;
begin
  SearchArray := VarArrayCreate([0,1], VarVariant);
  SearchArray[0] := 'T#more''wo';
  SearchArray[1] := 'One';

  ADOQuery.Locate('FieldName1;FieldName2', SearchArray, []);

1 个答案:

答案 0 :(得分:0)

请参阅下面的更新;我找到了一个至少值得测试的解决方法。

即使使用Sql Server表,#也不应该被转义。

以下代码在D7..XE8

中正常工作
procedure TForm1.Button1Click(Sender: TObject);
begin
  AdoQuery1.Locate('country;class', VarArrayOf(['GB', Edit1.Text]), []);
end;

Edit1.Text包含' D#E'时,我认为您的问题必须在其他地方。重新启动机器后,尝试使用该代码进行极简主义项目。

更新:如评论中所述,.Locate表达式存在问题 传递给GetFilterStr(在ADODB.Pas中)包含#后跟单引号。尝试和 为此解决了问题,我已将GetFilterStr移植到我的代码中并且已经完成了 我注意到,我一直在尝试使用它来构建我的AdoQuery上的记录集过滤器 这是.Locate在声明

中的作用
FLookupCursor.Filter := LocateFilter;

我正在使用的代码,包括我的"更正"版本GetFilterStr,位于下方。

我还没想到的是如何避免在

上出现异常
    AdoQuery1.Recordset.Filter := S;

当过滤器表达式不产生记录时。

(顺便说一句,为方便起见,我在D7中这样做,但是使用XE8' GetFilterStr,这就是为什么我必须将{{1}的引用注释掉的原因}})

ftFixedWideChar

更新2:请尝试以下操作:

  • 将Data.Win.ADODB.Pas复制到您的项目目录

  • 在其中,用上面的版本替换GetFilterExpr,确保UseOriginal 没有定义,并且在Case语句中恢复了ftFixedWideChar。

  • 构建并运行项目

无论如何,在XE8中,我的测试平台现在正确地找到()一个以function GetFilterStr(Field: TField; Value: Variant; Partial: Boolean = False): WideString; // From XE8 Data.Win.ADODB var Operator, FieldName, QuoteCh: WideString; begin QuoteCh := ''; Operator := '='; FieldName := Field.FieldName; if Pos(' ', FieldName) > 0 then FieldName := WideFormat('[%s]', [FieldName]); if VarIsNull(Value) or VarIsClear(Value) then Value := 'Null' else case Field.DataType of ftDate, ftTime, ftDateTime: QuoteCh := '#'; ftString, ftFixedChar, ftWideString://, ftFixedWideChar: begin if Partial and (Value <> '') then begin Value := Value + '*'; Operator := ' like '; { Do not localize } end; {.$define UseOriginal} {$ifdef UseOriginal} if Pos('''', Value) > 0 then QuoteCh := '#' else QuoteCh := ''''; {$else} QuoteCh := ''''; if Pos('''', Value) > 0 then begin QuoteCh := ''; Value := QuotedStr(Value); end; {$endif} end; end; Result := WideFormat('(%s%s%s%s%2:s)', [FieldName, Operator, QuoteCh, VarToWideStr(Value)]); end; procedure TForm1.CreateFilterExpr; var S : String; begin // clear any existing filter AdoQuery1.Recordset.Filter := adFilterNone; AdoQuery1.Refresh; if edFilter.Text = '' then Exit; S := GetFilterStr(AdoQuery1.FieldByName('Applicant'), edFilter.Text, cbPartialKey.Checked); // Add the filter expr to Memo1 so we can inspect it Memo1.Lines.Add(S); try AdoQuery1.Recordset.Filter := S; AdoQuery1.Refresh; except end; end; procedure TForm1.FilterClick(Sender: TObject); begin CreateFilterExpr; end; '结尾的字段 (如果指定#',则包含其中任何一个。(我无法在XE4 / 5中进行测试 因为自从我上周升级到Win10后,我的XE4现在说它没有执照,感谢EMBA!)

我匆匆将此称为解决方案,甚至是解决方案,但它至少值得测试。 我不确定我是否会将loPartialKey的原始版本称为“{1}}”,因为我不确定 什么用例它对含有引号的值的处理是为了处理。