Delphi Tstringlist,是否将字符串作为带引号的逗号分隔字符串?

Delphi Tstringlist,是否将字符串作为带引号的逗号分隔字符串?,delphi,csv,tstringlist,Delphi,Csv,Tstringlist,我有一个Tstringlist,其中包含数据库表中使用的键列表。 我想用一种简单的方法生成一个包含所有键的字符串,每个键用逗号分隔,并用单引号括起来。 这样就可以在SQL“in”语句中使用它 例如,其中字段x位于('1','2','3') 我尝试过使用quotechar,但在阅读commatext时忽略了它。 下面的代码 procedure junk; var SL : Tstringlist; s : string; begin SL := Tstringlist.Create;

我有一个Tstringlist,其中包含数据库表中使用的键列表。 我想用一种简单的方法生成一个包含所有键的字符串,每个键用逗号分隔,并用单引号括起来。 这样就可以在SQL“in”语句中使用它 例如,其中字段x位于('1','2','3')

我尝试过使用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
显示消息1、2、3-不带任何引号

我知道我可以做很长一段路,就像

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
将临时将
分隔符和
QuoteChar
更改为一些硬编码值。

CommaText(显然也是分隔文本)不能用来添加引号,因为它们对单字字符串和多字字符串的处理方式不同

检索CommaText时,列表中包含空格的任何字符串, 逗号或引号将包含在双引号和任何双引号中 字符串中的引号将重复

似乎没有任何单独与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);
输出为:

“一”,“两个字”,“三”


TStrings.DelimitedText
方法仅在需要时引用字符串:当有某个链接
O'ne
时,它将打印为
'O'ne'
——即它将双引号

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;
您可以通过将便利分隔符和
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或更高版本,则可以使用类帮助器:

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;
然后将输出:

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

我用类似的方法解决了一个类似的问题:

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

我已经试过了,没有什么区别,结果仍然是1、2、3,值周围没有单引号。@user3209752:可能是因为不需要引用字符串,因为字符串中没有空格或逗号。尝试使用包含逗号和/或空格的值…但我需要在最后一个逗号分隔的字符串中引用它们,否则使用该字符串的SQL将把它们解释为列名,而不是字符串文本。ie FieldX IN(一、二、三)与FieldX IN('1'、'2'、'3')非常不同。文档实际上支持您:
在检索DelimitedText时,结果值以两种方式分隔单个字符串:每个字符串由QuoteChar属性指定的引号字符包围(前后)。此外,单个字符串由Delimiter属性指定的字符分隔。
。它只是不做第一部分中所述的事情(至少不针对单个单词字符串),也不做您可能做的事情wonder@fantaghirocco哦?那可能是什么?这是我的一个测试:你试过你的代码吗?它没有按预期打印引号。似乎没有一个简单的方法…@Fantagirocco,正如你在最后一行看到的。但重读一遍,我关于CommaText的第一次声明并没有如期通过。感谢在我最后的评论中,我没有注意到使用了
QuotedStr
:显然它打印了预期的内容。我的道歉O:-)有用的回答。我已经编写了相当于一个单元的帮助函数,正如您建议的那样,可以执行ToSQL.text、ToSQL.date等操作,也可以执行相反的操作,例如FromDB.date、FromSQL.time等,以便使用delphi变量轻松生成sql。本质上,您是在建议将我上面的“long-way”代码以打包形式放在该单元中。整洁是个好主意,但并没有真正回答我的实际问题。关于Tstringlist是否能自己做到这一点,它不能-但通过使用班级助手,你可以让它看起来像能做到的一样:-)我想我会接受你的回答,部分原因是你实际上已经回答了这个问题——尽管你说这是不可能做到的,部分原因是按照你的建议去做,并将我的“long-way”代码放在另一个helper函数中,确实让它看起来像是Tstringlist在做这项工作。这比我的“long-way”还要复杂!您通过输入字符串中的分隔符来告诉字符串列表期望得到什么,这是我无法做到的,因为输入是在没有分隔符的其他地方生成的,另外,您还显式地在每个字符串周围加引号,这与我无法做到的原因相同。首先,我无法更改stringlist包含的内容。看起来我的“长途跋涉”的变体将是
sl
对象的字符串永远不会改变的唯一方式。您可以分配分隔符
QuoteChar
,即使在列表中填充了值。这只会影响分隔文本的输出。如果字符串列表中的某个条目包含逗号,则尝试这样做是不够的,因为不转义引号字符将失败。。。或者如果其中一个条目包含一个引号。。。