如果不使用别名,如何从内部查询中识别连接列?

时间:2015-06-26 16:38:08

标签: sql oracle11g

由于一些动态SQL的复杂性,我需要将两个表连接在一起并从结果中查询,就好像它是一个表一样。扭曲的是我必须SELECT *对内部查询 - 我不能对列进行别名。似乎没有办法在外部查询中识别这些列。

以这些表格为例

CREATE TABLE test_tab1 (join_key NUMBER, tab1_uqcol VARCHAR2(30));
CREATE TABLE test_tab2 (join_key NUMBER, tab2_uqcol VARCHAR2(30));
INSERT INTO test_tab1 VALUES (1, 'table 1 only');
INSERT INTO test_tab2 VALUES (1, 'table 2 only');

我可以轻松地对其唯一列进行过滤

SELECT *
FROM (
    SELECT *
    FROM test_tab1 t1
    INNER JOIN test_tab2 t2
    ON t1.join_key = t2.join_key
) joined
WHERE tab1_uqcol LIKE 'table%';

但如果我尝试引用他们共同的专栏......

SELECT *
FROM (
    SELECT *
    FROM test_tab1 t1
    INNER JOIN test_tab2 t2
    ON t1.join_key = t2.join_key
) joined
WHERE join_key = 1;

然后它告诉我join_key是无效的标识符。同上t1.join_keytest_tab1.join_key"t1.JOIN_KEY""T1.JOIN_KEY""TEST_TAB1.JOIN_KEY"。如何识别这些星级选定的列?

2 个答案:

答案 0 :(得分:1)

您不需要使用别名,但您需要更明确地在派生表中命名列。例如......

    SELECT *
    FROM (
        SELECT t1.join_key, t1.tab1_uqcol, t2.tab2_uqcol
        FROM test_tab1 t1
        INNER JOIN test_tab2 t2
        ON t1.join_key = t2.join_key
    ) joined
    WHERE join_key = 1;

由于您正在使用内部联接,因此无需区分两个不同的join_key列。您只需在内部查询中列出其中一个,以便外部查询不会混淆。

答案 1 :(得分:1)

您的查询无效SQL。子查询中指定的列必须是唯一的,*只是所有列的语法糖。即使你说的那个也很容易'无效。

看来我错了。 Oracle似乎不遵循ANSI SQL并允许子查询,这可能会产生不明确的列集。事实上,SQLFiddle需要在DML端完成插入,因此它提供了误报。

<强> SQL Fiddle

架构设置(Oracle 11g R2)

CREATE TABLE test_tab1 (join_key NUMBER, tab1_uqcol VARCHAR2(30));
CREATE TABLE test_tab2 (join_key NUMBER, tab2_uqcol VARCHAR2(30));

查询1

INSERT INTO test_tab1 VALUES (1, 'table 1 only');
INSERT INTO test_tab2 VALUES (1, 'table 2 only');

SELECT *
FROM (
    SELECT *
    FROM test_tab1 t1
    INNER JOIN test_tab2 t2
    ON t1.join_key = t2.join_key
) joined

<强> Results

ORA-00900: invalid SQL statement

有三种方法可以修改您的查询以解决此问题:

  1. 确保所有表都有唯一的列(即join_key1,join_key2)。
  2. 明确列出所有具有动态生成的别名的列,保证是唯一的,例如tablename + columnname(即t1.join_key AS test_tab1_join_key,t2.join_key AS test_tab2_join_key ...)。
  3. 通过第二对连接列显式列出列的子集(即t1.join_key,t1.tab1_uqcol,t2.tab2_uqcol)。
  4. 避免一起使用子查询(SQLFiddle example)。
  5. 这三个都有不同的缺点,因此取决于您需要如何使用此查询。第二个保证为所有可能的表生成可引用的列集。第三种方法可能稍微容易一些,但如果两个表共享除连接列以外的列的相同列名,则可能会失败。

    编辑:我的立场得到了纠正。你是对的。 Oracle确实允许您引用子查询中的重复列。即使Oracle允许你这样做,我仍然会避免它,因为它是不好的做法。它也不会在大多数RDMS中生成有效的SQL。

    我将保留答案,因为除非有人发现未记录的方式从外部查询中引用重复的列名,否则您可能别无选择,只能修改内部查询。