【问题标题】:Print the data in ResultSet along with column names打印 ResultSet 中的数据以及列名
【发布时间】:2014-08-05 10:29:22
【问题描述】:

我正在通过 Java 从 SQL 数据库中检索列名。我知道我也可以从ResultSet 检索列名。所以我有这个sql查询

 select column_name from information_schema.columns where table_name='suppliers'

问题是我不知道如何从ResultSet 获取列名,而我的代码是

public void getAllColumnNames() throws Exception{

String sql = "SELECT column_name from information_schema.columns where table_name='suppliers'";

PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery(sql);
 // extract values from rs


}

【问题讨论】:

  • 使用 jdbc 在 java 和 scala 中打印结果集几乎相同。为 scala 用户添加了 scala 标签

标签: java mysql scala jdbc


【解决方案1】:
ResultSet resultSet = statement.executeQuery("SELECT * from foo");
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while (resultSet.next()) {
    for (int i = 1; i <= columnsNumber; i++) {
        if (i > 1) System.out.print(",  ");
        String columnValue = resultSet.getString(i);
        System.out.print(columnValue + " " + rsmd.getColumnName(i));
    }
    System.out.println("");
}

参考:Printing the result of ResultSet

【讨论】:

    【解决方案2】:

    1) 代替PreparedStatement 使用Statement

    2) 在ResultSet中执行查询后,在rs.getString()的帮助下提取值为:

    Statement st=cn.createStatement();
    ResultSet rs=st.executeQuery(sql);
    while(rs.next())
    {
        rs.getString(1); //or rs.getString("column name");
    }
    

    【讨论】:

    • OP不知道列名,他/她怎么能用rs.getString("column name");
    【解决方案3】:

    进一步用作

    rs.getString(1);
    rs.getInt(2);
    

    1,2为表的列号,根据coloumn的数据类型设置int或string

    【讨论】:

      【解决方案4】:

      对于那些想要将结果集打印为 util 类的更好版本的人 这对于打印结果集非常有帮助,并且可以通过单个 util 执行许多操作...感谢 Hami Torun!

      在这个类中printResultSet 以通用方式使用ResultSetMetaData 看看它..

      导入java.sql.*; 导入 java.util.ArrayList; 导入 java.util.List; 导入 java.util.StringJoiner; 公共最终类 DBTablePrinter { /** * CHARVARCHAR 的列类型类别 * 和类似的文本列。 */ 公共静态最终 int CATEGORY_STRING = 1; /** * TINYINTSMALLINT 的列类型类别, * INTBIGINT 列。 */ 公共静态最终 int CATEGORY_INTEGER = 2; /** * REALDOUBLE 的列类型类别, * 和 DECIMAL 列。 */ 公共静态最终 int CATEGORY_DOUBLE = 3; /** * 日期和时间相关列的列类型类别,例如 * DATETIMETIMESTAMP 等。 */ 公共静态最终 int CATEGORY_DATETIME = 4; /** * BOOLEAN 列的列类型类别。 */ 公共静态最终 int CATEGORY_BOOLEAN = 5; /** * 类型名称的类型的列类型类别 * 将被打印而不是内容,例如BLOB, * BINARYARRAY 等。 */ 公共静态最终 int CATEGORY_OTHER = 0; /** * 默认查询和打印的最大行数。 */ 私有静态最终 int DEFAULT_MAX_ROWS = 10; /** * 文本列的默认最大宽度 *(如VARCHAR)列。 */ 私有静态最终 int DEFAULT_MAX_TEXT_COL_WIDTH = 150; /** * 从表tableName 打印行的重载方法 * 使用给定的数据库连接进行标准输出 *conn。总行数将被限制为 * {@link #DEFAULT_MAX_ROWS} 和 * {@link #DEFAULT_MAX_TEXT_COL_WIDTH} 将用于限制 * 文本列的宽度(如VARCHAR 列)。 * * @param conn 数据库连接对象 (java.sql.Connection) * @param tableName 数据库表的名称 */ 公共静态无效打印表(连接连接,字符串表名){ printTable(conn, tableName, DEFAULT_MAX_ROWS, DEFAULT_MAX_TEXT_COL_WIDTH); } /** * 从表tableName 打印行的重载方法 * 使用给定的数据库连接进行标准输出 *conn。总行数将被限制为 * maxRows 和 * {@link #DEFAULT_MAX_TEXT_COL_WIDTH} 将用于限制 * 文本列的宽度(如VARCHAR 列)。 * * @param conn 数据库连接对象 (java.sql.Connection) * @param tableName 数据库表的名称 * @param maxRows 最大数量。要查询和打印的行 */ 公共静态无效打印表(连接连接,字符串表名,int maxRows){ printTable(conn, tableName, maxRows, DEFAULT_MAX_TEXT_COL_WIDTH); } /** * 从表tableName 打印行的重载方法 * 使用给定的数据库连接进行标准输出 *conn。总行数将被限制为 * maxRows 和 * maxStringColWidth 将用于限制 * 文本列的宽度(如VARCHAR 列)。 * * @param conn 数据库连接对象 (java.sql.Connection) * @param tableName 数据库表的名称 * @param maxRows 最大数量。要查询和打印的行 * @param maxStringColWidth 最大值。文本列的宽度 */ 公共静态无效打印表(连接连接,字符串表名,int maxRows,int maxStringColWidth){ if (conn == null) { System.err.println("DBTablePrinter 错误:没有连接到数据库(连接为空)!"); 返回; } if (tableName == null) { System.err.println("DBTablePrinter 错误:没有表名(tableName 为空)!"); 返回; } if (tableName.length() == 0) { System.err.println("DBTablePrinter 错误:空表名!"); 返回; } 如果(最大行数 * 使用 {@link #DEFAULT_MAX_TEXT_COL_WIDTH} 将结果集标准输出 * 限制文本列的宽度。 * * @param rs ResultSet 打印 */ 公共静态无效打印结果集(结果集rs){ printResultSet(rs, DEFAULT_MAX_TEXT_COL_WIDTH); } /** * 打印行的重载方法 * ResultSet 使用maxStringColWidth 标准输出 * 限制文本列的宽度。 * * @param rs ResultSet 打印 * @param maxStringColWidth 最大值。文本列的宽度 */ 公共静态无效打印结果集(结果集rs,int maxStringColWidth){ 尝试 { 如果(rs == null){ System.err.println("DBTablePrinter 错误:结果集为空!"); 返回; } 如果(rs.isClosed()){ System.err.println("DBTablePrinter 错误:结果集已关闭!"); 返回; } if (maxStringColWidth columns = new ArrayList(columnCount); // 表名列表。如果它是连接的,则可以是多个 // 表查询 列出 tableNames = new ArrayList(columnCount); // 获取列及其元数据。 // 注意: rsmd.getXXX 方法的 columnIndex 开始于 1 而不是 0 for (int i = 1; i maxStringColWidth) { value = value.substring(0, maxStringColWidth - 3) + "..."; } 休息; } // 调整列宽 c.setWidth(value.length() > c.getWidth() ? value.length() : c.getWidth()); c.addValue(值); } // for 循环 columnCount 结束 行数++; } // while 结束 (rs.next) /* 至此我们已经遍历元数据,得到 columns 并创建了所有 Column 对象,迭代 ResultSet 行,填充列值并调整 列宽。 我们还不能开始打印,因为我们必须准备 行分隔符字符串。 */ // 为了好玩,我将使用 StringBuilder StringBuilder strToPrint = new StringBuilder(); StringBuilder rowSeparator = new StringBuilder(); /* 准备要打印的列标签以及行分隔符。 它应该看起来像这样: +--------+------------+------------+-----------+(行分隔器) | EMP_NO |出生日期 | FIRST_NAME | LAST_NAME | (标签行) +--------+------------+------------+-----------+(行分隔器) */ // 遍历列 对于(C列:列){ int 宽度 = c.getWidth(); // 将列标签居中 打印字符串; 字符串名称 = c.getLabel(); int diff = 宽度 - name.length(); 如果((差异%2)== 1){ // diff 不能被 2 整除,宽度加 1(和 diff) // 这样我们就可以在左右两边有相等的填充 // 列标签。 宽度++; 差异++; c.setWidth(宽度); } int paddingSize = diff / 2; // InteliJ 说强制转换为 int 是多余的。 // 感谢 stackoverflow.com 上的 user102008 的酷字符串中继器代码 字符串填充 = new String(new char[paddingSize]).replace("\0", ""); toPrint = "|" + 填充 + 名称 + 填充 + " "; // END 居中列标签 strToPrint.append(toPrint); rowSeparator.append("+"); rowSeparator.append(new String(new char[width + 2]).replace("\0", "-")); } 字符串 lineSeparator = System.getProperty("line.separator"); // 这真的有必要吗? lineSeparator = lineSeparator == null ? "\n" : 行分隔符; rowSeparator.append("+").append(lineSeparator); strToPrint.append("|").append(lineSeparator); strToPrint.insert(0, rowSeparator); strToPrint.append(rowSeparator); StringJoiner sj = new StringJoiner(", "); 对于(字符串名称:tableNames){ sj.add(名称); } 字符串信息 = "打印" + rowCount; 信息 += 行数 > 1 ? " 来自 " 的行 : " 来自 " 的行; 信息 += tableNames.size() > 1 ? “表”:“表”; 信息 += sj.toString(); System.out.println(info); // 打印出格式化的列标签 System.out.print(strToPrint.toString()); 字符串格式; // 打印行 对于 (int i = 0; 我 * 整数不应被截断,因此列宽应 * 可以在没有列宽限制的情况下进行调整。文本列应该是 * 左对齐,可以截断到最大值。列宽等... *

      * 也可以看看: * java.sql.Types * * @param type 通用 SQL 类型 * @return 该类型所属的类别 */ 私有静态 int whichCategory(int type) { 开关(类型){ 案例类型.BIGINT: 案例类型.TINYINT: 案例类型.SMALLINT: 案例类型.INTEGER: 返回类别整数; 案例类型.REAL: 案例类型.DOUBLE: 案例类型。十进制: 返回 CATEGORY_DOUBLE; 案例类型。日期: 案例类型。时间: 案例类型.TIME_WITH_TIMEZONE: 案例类型.TIMESTAMP: 案例类型.TIMESTAMP_WITH_TIMEZONE: 返回类别日期时间; 案例类型。布尔值: 返回 CATEGORY_BOOLEAN; 案例类型.VARCHAR: 案例类型.NVARCHAR: 案例类型.LONGVARCHAR: 案例类型.LONGNVARCHAR: 案例类型.CHAR: 案例类型.NCHAR: 返回类别字符串; 默认: 返回 CATEGORY_OTHER; } } /** * 表示一个数据库表列。 */ 私有静态类列{ /** * 列标签。 */ 私有字符串标签; /** * 定义的列的通用 SQL 类型 * * java.sql.Types * . */ 私有 int 类型; /** * 定义的列的通用 SQL 类型名称 * * java.sql.Types * . */ 私有字符串类型名; /** * 将根据列标签调整的列宽 * 和要打印的值。 */ 私人 int 宽度 = 0; /** * ResultSet 每一行的列值。 */ 私有列表值 = new ArrayList(); /** * 使用String.format 进行文本对齐标记。 * 空字符串 ("") 证明正确, * 破折号 (-) 左对齐。 * * @see #justifyLeft() */ 私人字符串 justifyFlag = ""; /** * 列类型类别。列将根据 * 到它们的列类型和特定需要正确打印它们。 */ 私有 int typeCategory = 0; /** * 用列标签构造一个新的Column, * 通用 SQL 类型和类型名称(定义见 * * java.sql.Types * ) * * @param label 列标签或名称 * @param type 通用 SQL 类型 * @param typeName 通用 SQL 类型名称 */ 公共列(字符串标签,整数类型,字符串类型名称){ this.label = 标签; this.type = 类型; this.typeName = typeName; } /** * 返回列标签 * * @return 列标签 */ 公共字符串 getLabel() { 返回标签; } /** * 返回列的通用 SQL 类型 * * @return 通用 SQL 类型 */ 公共 int getType() { 返回类型; } /** * 返回列的通用 SQL 类型名称 * * @return 通用 SQL 类型名称 */ 公共字符串 getTypeName() { 返回类型名; } /** * 返回列的宽度 * * @return 列宽 */ 公共 int getWidth() { 返回宽度; } /** * 设置列宽为width * * @param width 列的宽度 */ 公共无效setWidth(int宽度){ this.width = 宽度; } /** * 添加String 表示 (value) * 此列对象的 {@link #values} 列表的值。 * 这些值将来自 a 的每一行 * * 结果集 * 数据库查询。 * * @param value 要添加到 {@link #values} 的列值 */ 公共无效添加值(字符串值){ values.add(value); } /** * 返回行索引i 处的列值。 * 注意索引从 0 开始,所以getValue(0) * 将从第一行获取该列的值 * 一个 * 结果集。 * * @param i 要获取的列值的索引 * @return 值的字符串表示形式 */ 公共字符串 getValue(int i) { 返回值.get(i); } /** * 返回 {@link #justifyFlag} 的值。专栏 * 值将使用String.format 和 * 此标志将用于右对齐或左对齐文本。 * * @return 此列的 {@link #justifyFlag} * @see #justifyLeft() */ 公共字符串 getJustifyFlag() { 返回正当化标志; } /** * 将 {@link #justifyFlag} 设置为 "-" 以便 * 打印时列值将左对齐 *String.format。通常数字是正确的 * 对齐,文本将左对齐。 */ 公共无效justifyLeft(){ this.justifyFlag = "-"; } /** * 返回列的通用 SQL 类型类别 * * @return 列的{@link #typeCategory} */ 公共 int getTypeCategory() { 返回类型类别; } /** * 设置列的{@link #typeCategory} * * @param typeCategory 类型类别 */ 公共无效 setTypeCategory(int typeCategory) { this.typeCategory = typeCategory; } } }

      这是执行此操作的 scala 版本...它将以通用方式打印列名和数据...

      def printQuery(res: ResultSet): Unit = {
          val rsmd = res.getMetaData
          val columnCount = rsmd.getColumnCount
          var rowCnt = 0
          val s = StringBuilder.newBuilder
          while (res.next()) {
      
            s.clear()
            if (rowCnt == 0) {
              s.append("| ")
              for (i <- 1 to columnCount) {
                val name = rsmd.getColumnName(i)
                s.append(name)
                s.append("| ")
              }
              s.append("\n")
            }
            rowCnt += 1
            s.append("| ")
            for (i <- 1 to columnCount) {
              if (i > 1)
                s.append(" | ")
              s.append(res.getString(i))
            }
            s.append(" |")
            System.out.println(s)
          }
          System.out.println(s"TOTAL: $rowCnt rows")
        }
      

      【讨论】:

      • 第 100 行附近的 Java 类中似乎出了点问题,它说“if (maxRows”并且该行在那里结束 编辑:从提供的 github 链接复制,而不是上面的答案,github 类作品
      【解决方案5】:

      看看documentation。你犯了以下错误。 首先,ps.executeQuery() 没有任何参数。相反,您将 SQL 查询传递给它。

      其次,关于prepared statement,如果要传递任何参数,您必须使用? 符号。然后使用

      绑定它
      setXXX(index, value) 
      

      这里xxx代表数据类型。

      【讨论】:

        【解决方案6】:

        您可以使用TableSaw library,这是一个很棒的 Java 数据科学/数据框架库。那么代码就很简单了:

        System.out.println(Table.read().db(resultSet).print());
        

        【讨论】:

          【解决方案7】:

          对于您要执行的操作,您可以使用Statement 而不是PreparedStatement。您的代码可能会被修改为-

          String sql = "SELECT column_name from information_schema.columns where table_name='suppliers';";
          
          Statement s  = connection.createStatement();
          ResultSet rs = s.executeQuery(sql);
          

          希望这会有所帮助。

          【讨论】:

            猜你喜欢
            • 2021-10-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-13
            • 1970-01-01
            相关资源
            最近更新 更多