从具有基于表达式的SELECT的结果集中获取列而不使用别名

时间:2014-07-07 20:53:53

标签: sql oracle odbc sqlplus oci

这应该是一个基本问题,但在被要求时我无法回答。对不起,如果它太广泛了!

SELECT * FROM
(
  SELECT MYGROUPKEY,MAX(MYCOLUMN)/MIN(MYCOLUMN) FROM
  MYTABLE
  GROUP BY MYGROUPKEY
) MYSUBQUERY;

此查询在语法上有效。但是,如果他们必须尝试使用​​某个标识符,有人会如何获取此结果集的第二列? (该列从未提供别名)。如何在SQL*Plus中格式化。 (COL <column_name> FORMAT A<num>

这是文本MAX(MYCOLUMN)/MIN(MYCOLUMN)的前几个字符。

我理解,RDBMS概念并不喜欢这样。但仍然为什么数据库会执行这个SQL呢?它永远不会命名结果集的列,除非查询携带它?

2 个答案:

答案 0 :(得分:3)

假设表达式少于30个字符

SQL> column "MAX(MYCOLUMN)/MIN(MYCOLUMN)" format <<some format>>

应该有效。您可以实际查看SQL * Plus中的原始列标题(在应用任何格式之前)以查看分配的别名是什么。根据实际表达式,可以应用各种规则 - 例如,消除空格,并将表达式限制为30个字符。它通常更容易复制和从SQL * Plus粘贴并用双引号括起指定的别名。

答案 1 :(得分:2)

有一个隐式别名,它是删除了任何空格的表达式。但由于表达式包含对标识符无效的字符,因此必须引用"MAX(MYCOLUMN)/MIN(MYCOLUMN)"。您也可以在SQL * Plus column命令中引用它。

e.g。

SELECT MYGROUPKEY, "MAX(MYCOLUMN)/MIN(MYCOLUMN)" FROM
(
  SELECT MYGROUPKEY,MAX(MYCOLUMN) / MIN(MYCOLUMN)
  FROM MYTABLE
  GROUP BY MYGROUPKEY
) MYSUBQUERY;

SQL Fiddle

但是还有一个皱纹。由于标识只能是30个字符,如果表达式比表达式长,则隐式别名也太长,无法在SQL本身中引用。这将是get an ORA-00972

SELECT MYGROUPKEY, "MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000)" FROM
(
  SELECT MYGROUPKEY,MAX(MYCOLUMN) / MIN(MYCOLUMN) * (1000 / 1000)
  FROM MYTABLE
  GROUP BY MYGROUPKEY
) MYSUBQUERY;

最好添加自己的别名,即使是较短的表达式。

但有时您仍然可以使用较长的别名,例如通过JDBC,它出现在元数据中(因为它here作为列标签)。访问与SQL Fiddle相同的数据的测试部分:

pStmt = (OraclePreparedStatement) conn.prepareStatement(
  "SELECT MYGROUPKEY,MAX(MYCOLUMN) / MIN(MYCOLUMN) * (1000 / 1000) "
    + "FROM MYTABLE GROUP BY MYGROUPKEY");
rSet = (OracleResultSet) pStmt.executeQuery();
OracleResultSetMetaData rsmd = (OracleResultSetMetaData) rSet.getMetaData();

for( int i=1; i <= rsmd.getColumnCount(); i++ ) {
  System.out.println( "Column label: " + rsmd.getColumnLabel(i));
  System.out.println( "Column Type:  " + rsmd.getColumnTypeName(i));
  System.out.println();
}

while (rSet.next())
{
  System.out.println("MYGROUPKEY: " + rSet.getInt("MYGROUPKEY"));
  System.out.println("MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000): "
    + rSet.getInt("MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000)"));
}

产生输出:

Column label: MYGROUPKEY
Column Type:  NUMBER

Column label: MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000)
Column Type:  NUMBER

MYGROUPKEY: 1
MAX(MYCOLUMN)/MIN(MYCOLUMN)*(1000/1000): 2

请注意,元数据报告的列标签/名称与小提琴中显示的相同,删除了空格的表达式;并且我可以将其用作getInt()的参数,即使它超过30个字符。