使用别名的 SELECT 和不使用别名的 SELECT 有什么区别 - Oracle 11g

7
我有一张名为table1的表格。
该表格包含许多列,其中一列是一个对象,它由3个子列构成,我们称其为value1value2value3
假设该对象类型的名称为object_type1
我准备了一个投影查询,它的形式如下:
Select typed_column.value1 
from table1

这个投影在Oracle 11g上无法工作,它会显示“无效标识符”。

因此,我尝试将表的名称添加到所选列中:

Select table1.typed_column.value1 
from table1

这也没有起作用。

但是当我使用别名时:

Select tab1.typed_column.value1 
from table1 tab1

它正在运行。

我还发现另一种解决方案也可以使用(使用treat函数):

Select treat(typed_column as object_type1).value1 
from table1

我的问题是:别名(alias)的作用是什么,数据库如何实际映射对象类型的列?
为什么我的前两个查询没有正确工作?
我准备了一个表和类型,表的DDL如下: CREATE TABLE table1 ( --....很多其他列前面 typed_column OBJECT_TYPE_1 ) 对象的DDL如下: CREATE OR REPLACE TYPE "MY_SCHEMA"."OBJECT_TYPE_1" is object ( value1 varchar2(100), value2 date, value3 date )

1
你能分享一下你的表DDL吗?这样我们就可以尝试一下你的用例了。 - thatjeffsmith
1
因为它可能会导致内部捕获。文档:link1link2显示了类似于您的示例。 - Ponder Stibbons
这个查询语句:Select table1.typed_column.value1 from table1,如何进行内部捕获呢? 您的评论很有价值,但它并不是对问题的回答。我仍然不知道在这种特定情况下别名是如何起作用的。 - Bartosz Olchowik
@thatjeffsmith DDL现在可用。 - Bartosz Olchowik
2个回答

3

您需要这样做,因为这是文档所说的 ;)

2.1.8.1 当表别名是必需时

在解析引用时可能需要使用表别名来避免问题。

Oracle Database 要求您使用表别名限定任何对象子程序或属性的点符号引用,以避免内部捕获和类似问题解析引用

好的,那么这个规则存在的原因是什么呢?

考虑下面的场景:

create type emp_obj as object (
  employee_id   integer,
  employee_name varchar2(100),
  department_id integer
);
/

create table departments (
  department_id integer,
  manager       emp_obj
);
/

create table manager (
  employee_id   integer,
  employee_name varchar2(100),
  department_id integer
);

select * from departments d
where  exists ( 
  select * from manager
  where  manager.department_id = d.department_id --which manager.department_id?
);

在这个例子中:

  • departments表带有一个带有department_id属性的manager对象列
  • manager表带有一个department_id

那么where manager.department_id会解析成什么?!

在没有别名的情况下,它可以是两个表中的任何一个。当您存储对象时,可能会出现以下情况:

<table_name>.<column_name> 和同一查询中另一个表中的<object_column_name>.<attribute_name> 相同!

当您开始添加/删除表中的列或类型中的属性时,这将创建名称解析...可能会有意外。

因此,为了避免这种情况,Oracle数据库强制使用别名。

就像在查询中两次使用相同的表时需要使用别名一样:

create table t (
  c1 int, c2 int
);

select * from t, t
where  c1 = 1;

ORA-00918: column ambiguously defined

select * from t t1, t t2
where  t1.c1 = 1;

no rows selected

请注意,规则有一个细化:
当直接引用对象表的顶层属性而不使用点符号时,使用表别名是可选的。例如,以下语句定义包含person_typ对象类型的两个表。person_obj_table是person_typ类型对象的对象表,contacts是一个关系表,其中包含一个person_typ对象的列。
创建对象表时,属性就是列。因此,上述歧义消失了。

-1

在查询中,不应该同时引用表的两边。如果你从A表中选择数据,不要选择A.B.C,只需从A中选择B.C即可。


1
这是我在第一个查询中所做的:Select typed_column.value1 from table1?还是你指的是其他的东西? - Bartosz Olchowik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接