Delphi Tstringlist,将字符串作为引号、逗号分隔的字符串获取?

Delphi Tstringlist, get strings as a quoted, comma delimited string?

我有一个包含数据库中使用的键列表的 Tstringlist table。 我想要一种简单的方法来生成一个包含所有键的字符串,每个键用逗号分隔并用单引号引起来。 这样它就可以在 SQL 'IN' 语句中使用 例如 WHERE FieldX IN ('One','Two','Three').

我试过使用 quotechar,但在读取 commatext 时它被忽略了。 例如下面的代码

procedure junk;
var
  SL : Tstringlist;
  s : string;
begin
 SL := Tstringlist.Create;
 SL.Delimiter :=','; //comma delimiter
 SL.QuoteChar := ''''; //single quote around strings
 SL.Add('One');
 SL.Add('Two');
 SL.Add('Three');
 try
   s :=  SL.commatext;
   showmessage(s);
 finally
   SL.Free;
 end; //finally
end; //junk

显示消息一、二、三 - 不带任何引号。

我知道我可以从长远来看,如

procedure junk;
var
  SL : Tstringlist;
  s : string;
  i : integer;
begin
 SL := Tstringlist.Create;
 SL.Delimiter :=','; //comma delimiter
 SL.Add('One');
 SL.Add('Two');
 SL.Add('Three');
 try
 s := '';
 for I := 0 to SL.Count - 1 do
    begin
    s := s +  ',' + '''' + SL[i] + '''';
    end;
 delete(s,1,1);
 showmessage(s);
 finally
   SL.Free;
 end;//finally
end;

但是有没有更简单的方法使用 Tstringlist 本身的属性?

使用 sl.DelimitedText 而不是 sl.CommaText 使其遵循您的设置。 CommaText 会暂时将 DelimiterQuoteChar 更改为一些硬编码值。

不能依赖 CommaText(显然还有 DelimitedText)来添加引号,因为它们对单个单词和多个单词字符串的处理方式不同。

When retrieving CommaText, any string in the list that include spaces, commas or quotes will be contained in double quotes, and any double quotes in a string will be repeated.

单独使用TStringList似乎没有任何组合,所以我建议您使用QuotedStr添加字符串。 以下设置随心所欲,无论字符串是单个单词还是多个单词:

 SL := Tstringlist.Create;
 SL.Delimiter :=','; //comma delimiter
 SL.StrictDelimiter := True;
// SL.QuoteChar := ''''; //single quote around strings
// SL.Add('One');
// SL.Add('Two words');
// SL.Add('Three');
 SL.Add(QuotedStr('One'));
 SL.Add(QuotedStr('Two words'));
 SL.Add(QuotedStr('Three'));
 s := SL.CommaText; // or SL.DelimitedText;
 showmessage(s);

输出为:

'One','Two words','Three'

TStrings.DelimitedText 方法仅在需要时引用字符串:当有内容时 link O'ne 这将打印为 'O''ne' - 即它加倍引号。

你可以实现你想要的设置一个方便的分隔符和 QuoteChar 属性 到 #0 值,然后用引号替换分隔符。

procedure junk;
var
  sl : Tstringlist;
  s: string;
begin
  sl := Tstringlist.Create;
  try
    sl.Delimiter := '|';
    sl.QuoteChar := #0;//no quote
    sl.Add('On''e');
    sl.Add('Two');
    sl.Add('Three');

    //escape the single quotes
    s := StringReplace(sl.DelimitedText, '''', '''''', [rfReplaceAll]);

    //replace the delimiters and quote the text
    s := '''' +  StringReplace(s, sl.Delimiter, ''',''', [rfReplaceAll]) + '''';

    WriteLn(s);

  finally
    sl.Free;
  end;
end;

如果您使用的是 D2006 或更高版本,您可以使用 CLASS 帮助程序:

USES Classes,StrUtils;

TYPE
  TStringListHelper = CLASS HELPER FOR TStrings
                        FUNCTION ToSQL : STRING;
                      END;

FUNCTION TStringListHelper.ToSQL : STRING;
  VAR
    S : STRING;

  FUNCTION QuotedStr(CONST S : STRING) : STRING;
    BEGIN
      Result:=''''+ReplaceStr(S,'''','''''')+''''
    END;

  BEGIN
    Result:='';
    FOR S IN Self DO BEGIN
      IF Result='' THEN Result:='(' ELSE Result:=Result+',';
      Result:=Result+QuotedStr(S)
    END;
    IF Result<>'' THEN Result:=Result+')'
  END;

此代码:

SL:=TStringList.Create;
SL.Add('One');
SL.Add('Two');
SL.Add('Number Three');
SL.Add('It''s number 4');
WRITELN('SELECT * FROM TABLE WHERE FIELD IN '+SL.ToSQL);

然后会输出:

SELECT * FROM TABLE WHERE FIELD IN ('One','Two','Number Three','It''s number 4')

我已经解决了类似的问题:

  s := ''' + StringReplace(sl.CommaText, ',', ''',''', [rfReplaceAll]) + '''