Oracle SQL - 从视图中选择比在视图中运行选择更多的行

Posted

技术标签:

【中文标题】Oracle SQL - 从视图中选择比在视图中运行选择更多的行【英文标题】:Oracle SQL - select from view more rows than running select in the view 【发布时间】:2013-08-27 15:01:09 【问题描述】:

当我运行这个 SQL 时,我得到了 116,463 行。 select * from appsdisc.appsdisc_phones_gen_v

当我运行视图定义脚本中的选择时,我得到了 11,702 行。

我不明白为什么结果集不同。

查看脚本如下。

CREATE OR REPLACE FORCE VIEW APPSDISC.APPSDISC_PHONES_GEN_V
(PARTY_ID, CUSTOMER_ID, CUSTOMER_NUMBER, PHONE_NUMBER, PHONE_TYPE)
AS 
SELECT party_id,
          customer_id,
          customer_number,
          phone_number,
          phone_type
     FROM appsdisc_phones_v pv1
    WHERE pv1.phone_type LIKE
             DECODE (TRIM (SUBSTR (pv1.attribute14, 1, 4)),
                     'FR', 'FR T%',
                     'PHONE')  
          AND pv1.contact_point_id =
                 (SELECT MIN (pv2.contact_point_id)
                    FROM appsdisc_phones_v pv2
                   WHERE pv2.customer_id = pv1.customer_id
                         AND pv2.phone_type LIKE
                                DECODE (
                                   TRIM (SUBSTR (pv1.attribute14, 1, 4)),
                                   'FR', 'FR T%',
                                   'PHONE'));

【问题讨论】:

运行相同的选择应该得到相同的结果,假设您连接到同一个数据库并且数据没有改变。您可以编辑问题以显示您用于计算结果集的代码吗? 您是以APPSDISC 用户身份运行独立查询,还是在另一个有自己的视图(可能不是表?)称为appsdisc_phones_v 的架构中运行? 【参考方案1】:

如果您完全按原样运行视图查询,并且您没有以APPSDISC 身份登录,那么您可能正在查询自己的表(或视图),因为appsdisc_phones_v 没有以架构为前缀在视图脚本中。希望这是一个开发环境,并且您有一个旧副本是有正当理由的。

这是我认为您看到的效果的演示。作为一个用户 (SOUSER1),我可以创建并填充一个表,并在其上添加一个视图,并将对该视图的访问权限授予其他用户。请注意,我不需要直接授予对基础表的访问权限。

create table my_table (id number);

insert into my_table
select level as id from dual connect by level <= 1000;

commit;

create view souser1.my_view as select * from my_table;

grant select on souser1.my_view to souser2;

select count(*) from my_view;

  COUNT(*)
----------
      1000 

select count(*) from my_table;

  COUNT(*)
----------
      1000 

我没有在视图语句中的 select 中指定架构,因此它将与视图所有者相同,在本例中为 SOUSER1

然后,作为第二个用户 (SOUSER2),我可以创建自己的表格版本,并且行数更少。查询视图仍然显示来自SOUSER1 表的行数,而不是我自己的。

create table my_table (id number);

insert into my_table
select level as id from dual connect by level <= 100;

commit;

select count(*) from souser1.my_view;

  COUNT(*)
----------
      1000 

如果我从原始视图运行查询,我会看到我自己的表副本,该副本更小,因为表名不符合架构名称 - 因此它默认为我自己的:

select count(*) from my_table;

  COUNT(*)
----------
       100 

因此,只要表有两个版本并且您没有指定要查询的版本,那么查看不同数量的行是有意义的。

在我的情况下,如果我尝试直接查询其他模式的表,我会收到错误,因为我没有授予任何权限:

select count(*) from souser1.my_table;

SQL Error: ORA-00942: table or view does not exist
00942. 00000 -  "table or view does not exist"

但是如果您没有有自己的副本、没有在登录时设置当前架构并且没有指向某个模式中的表的同义词。

【讨论】:

【参考方案2】:

Gordon 是对的,选择应该返回与视图相同的结果。在不同的模式、数据库或通过数据库链接运行查询等问题可以解释您所观察到的情况。您可以通过在下面的同一数据库和架构中运行两个 SQL 命令并比较两者返回的值来看到这一点。

首先,用SQL确认视图返回的行数:

SELECT COUNT(*) FROM APPSDISC.APPSDISC_PHONES_GEN_V;

然后用 SQL 确认视图查询返回的行数:

WITH RESULTS AS (
     SELECT party_id,
          customer_id,
          customer_number,
          phone_number,
          phone_type
     FROM appsdisc_phones_v pv1
    WHERE pv1.phone_type LIKE
             DECODE (TRIM (SUBSTR (pv1.attribute14, 1, 4)),
                     'FR', 'FR T%',
                     'PHONE')  
          AND pv1.contact_point_id =
                 (SELECT MIN (pv2.contact_point_id)
                    FROM appsdisc_phones_v pv2
                   WHERE pv2.customer_id = pv1.customer_id
                         AND pv2.phone_type LIKE
                                DECODE (
                                   TRIM (SUBSTR (pv1.attribute14, 1, 4)),
                                   'FR', 'FR T%',
                                   'PHONE')))
SELECT COUNT(*)
FROM RESULTS
/

两个查询应该返回相同的值。如果不是,那么这个问题不仅仅是返回不同行数的查询。

【讨论】:

以上是关于Oracle SQL - 从视图中选择比在视图中运行选择更多的行的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个连接(其他用户)中选择 Oracle 中的视图?

从 Oracle 9i 中的嵌套查询中选择

Oracle SQL 创建或替换带有/不带有列名的视图

在 Oracle PL/SQL 视图中管理 DB 链接

MySQL视图查询超慢,求解答

MySQL视图查询超慢,求解答