2

为了构建数据库系统,我使用一个简单的构建器来生成基于用户选择的选择查询。它有几个布尔值,然后按如下方式进行

    StringBuilder builder = new StringBuilder();
    builder.append("SELECT ");
    if(addOpen)
        builder.append("Open ");
    if(addHigh)
        builder.append("High ");
    if(addLow)
        builder.append("Low ");
    if(addSettle)
        builder.append("Settle ");
    builder.append("FROM " + tableName);

现在,我的问题是微不足道的 - 我需要包含逗号,但如果我包含逗号,那么它后面必须有一个值,所以我不能打开,或打开,关闭等。这个微不足道有没有一个巧妙的解决方案,但是对我来说出乎意料的困难?

4

6 回答 6

4

您是否正在寻找类似Apache Commons 的 StringUtils.join()方法?IE:

Collection<String> selections = Arrays.asList("Open", "Low");
String clause = StringUtils.join(selections, ',');

然后就

String sql = "SELECT " + clause + " FROM " + TableName;
于 2012-05-22T23:19:19.847 回答
3

1)典型的情况是你先验地知道你有多少物品。因此,您只需循环“n-1”,然后不要在最后一项后附加逗号。

2)一种可能的解决方案:

  ArrayList<string> items = new ArrayList<String>();
  if(addOpen);
    items.add("Open ");
  if(addHigh)
    items.add("High ");
  if(addLow)
    items.add("Low ");
  if(addSettle)
    items.add("Settle ");

  StringBuilder builder = new StringBuilder();
  int i=0;
  for (i=0; i < items.size() - 1; i++) {
    builder.append(items[i] + ",");
  }
  builder.append(items[i] + "FROM " + tableName);
  ...
于 2012-05-22T23:23:10.877 回答
1

有一个常见的技巧:始终选择一个您不感兴趣的常量:

builder.append ("SELECT 1 ");
if (addOpen)
    builder.append (", Open ");
if addHigh)
    builder.append (", High ");
if (addLow)
    builder.append (", Low ");
if (addSettle)
    builder.append (", Settle ");
builder.append ("FROM " + tableName);

另一种方法在另一个方向上起作用,尾随逗号:

builder.append ("SELECT ");
if (addOpen)
    builder.append ("Open, ");
if (addHigh)
    builder.append ("High, ");
if (addLow)
    builder.append ("Low, ");
if (addSettle)
    builder.append ("Settle, ");
builder.append ("1 FROM " + tableName);
于 2012-05-22T23:19:19.050 回答
1

有几种方法。第一个,这将是我的第一选择,根本不构建您的 SQL 语句,并且不显示字段。

第二个是构建字符串,然后删除最后一个逗号。

第三种是将每个字段名称放入一个数组中,并循环遍历数组,而不是将尾随逗号放在最后一个元素上。

于 2012-05-22T23:20:59.900 回答
0

在您的情况下,我使用类似于 Ryan Stewart 建议的解决方案,但我更喜欢 Google Guava而不是 Apache Commons。我更喜欢这个库,因为我觉得 Apache 库非常庞大且相互关联。下面是我将如何构建您的 SQL 字符串:

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import java.util.List;

public class SqlJoiner {
    public String buildSql(
            boolean addOpen,
            boolean addHigh,
            boolean addLow,
            boolean addSettle,
            String tableName
    ) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(tableName));
        Preconditions.checkArgument(addOpen | addHigh | addLow | addSettle );

        final List<String> clauses = Lists.newArrayList();

        if (addOpen) clauses.add("Open");
        if (addHigh) clauses.add("High");
        if (addLow) clauses.add("Low");
        if (addSettle) clauses.add("Settle");

        StringBuilder builder = new StringBuilder();
        builder.append("SELECT ");
        builder.append(Joiner.on(',').join(clauses));
        builder.append(" FROM " + tableName);
        return builder.toString();
    }

}

方法体开头的前提条件是确保至少有一个布尔选项始终为真,并且 tableName 不为 null 或为空。经常检查你的代码的前置条件,当你将来使用你的代码出错时,它会为你省去很多麻烦!

于 2012-05-23T06:32:54.860 回答
0

我使用的技巧(在通用的半无类型伪代码中)是:

 pad = ""    # Empty string

 builder = "SELECT ";
 if (addOpen)
     builder += pad + "Open";   pad = ", ";
 if (addHigh)
     builder += pad + "High";   pad = ", ";
 if (addLow)
     builder += pad + "Low";    pad = ", ";
 if (addSettle)
     builder += pad + "Settle"; pad = ", ";
 builder += "FROM " + TableName;

我见过的另一种方法是始终在条款之后包含逗号(或逗号空格),但在添加 FROM 子句之前将最后两个字符从值中删除。您的选择......即使您正在输出并且无法撤消追加,“pad”技术也有效。

于 2012-05-22T23:20:11.360 回答