【问题标题】:Oracle : Select distinct doesn't work when cursor inside a cursor (using cursor expression)Oracle:当游标在游标内时选择不同的不起作用(使用游标表达式)
【发布时间】:2015-02-03 11:47:23
【问题描述】:

我需要做一份报告,列出一些人的名单和他们的发票;由于我正在生成一些 XML(XML 发布者),因此一种方法是使用游标表达式。 SQL 请求由第一个游标组成,第一个游标提供联系人列表,第一个游标内的第二个游标列出每个联系人的发票。 问题是联系人 SQL 请求多次返回相同的联系人(实际上他有发票) 所以我需要使用 distinct,它不起作用!

为了有一个适用于任何地方的可重复性请求,我将使用基于 oracle 系统表 all_table 和 dual 的 sql 请求;

SQL 请求复制联系人列表:

select 
    'ALBERT EINSTEIN' CONTACT_NAME 
  from 
  ALL_VIEWS
  where view_name IN ( 'ALL_INDEXES', 'ALL_TABLES') ;

=> 艾尔伯特爱因斯坦 阿尔伯特·爱因斯坦

SQL 请求复制与联系人相关联的 (1) 发票列表:

SELECT 123456 INVOICE_NUMBER, 10000 INVOICE_AMOUNT, 'EUR' INVOICE_CURRENCY FROM DUAL  ;

=>

123456 10000 欧元

所以使用游标表达式的报表的 SQL 是:

select distinct
cursor (
  select 
    distinct 
    'ALBERT EINSTEIN' CONTACT_NAME 
    ,CURSOR (SELECT 123456 INVOICE_NUMBER, 10000 INVOICE_AMOUNT, 'EUR' INVOICE_CURRENCY FROM DUAL ) AS INVOICES
  from 
  ALL_VIEWS
  where view_name IN ( 'ALL_INDEXES', 'ALL_TABLES')
  ) AS CONTACTS
  from dual ;

所以生成 XML :

select dbms_xmlgen.getxml('
select distinct
cursor (
  select 
    distinct 
    ''ALBERT EINSTEIN'' CONTACT_NAME 
    ,CURSOR (SELECT 123456 INVOICE_NUMBER, 10000 INVOICE_AMOUNT, ''EUR'' INVOICE_CURRENCY FROM DUAL ) AS INVOICES
  from 
  ALL_VIEWS
  where view_name IN ( ''ALL_INDEXES'', ''ALL_TABLES'')
  ) AS CONTACTS
  from dual 
 ') from dual
;

那就是:

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <CONTACTS>
   <CONTACTS_ROW>
    <CONTACT_NAME>ALBERT EINSTEIN</CONTACT_NAME>
    <INVOICES>
     <INVOICES_ROW>
      <INVOICE_NUMBER>123456</INVOICE_NUMBER>
      <INVOICE_AMOUNT>10000</INVOICE_AMOUNT>
      <INVOICE_CURRENCY>EUR</INVOICE_CURRENCY>
     </INVOICES_ROW>
    </INVOICES>
   </CONTACTS_ROW>
   <CONTACTS_ROW>
    <CONTACT_NAME>ALBERT EINSTEIN</CONTACT_NAME>
    <INVOICES>
     <INVOICES_ROW>
      <INVOICE_NUMBER>123456</INVOICE_NUMBER>
      <INVOICE_AMOUNT>10000</INVOICE_AMOUNT>
      <INVOICE_CURRENCY>EUR</INVOICE_CURRENCY>
     </INVOICES_ROW>
    </INVOICES>
   </CONTACTS_ROW>
  </CONTACTS>
 </ROW>
</ROWSET>

=> 使用同一张发票显示两次相同的联系人,这是无用的,并且由于使用了 distinct,因此不期望出现。

通过评论第二个光标所有不同的作品:

select dbms_xmlgen.getxml('
select distinct
cursor (
  select 
    distinct 
    ''ALBERT EINSTEIN'' CONTACT_NAME 
    --,CURSOR (SELECT 123456 INVOICE_NUMBER, 10000 INVOICE_AMOUNT, ''EUR'' INVOICE_CURRENCY FROM DUAL ) AS INVOICES
  from 
  ALL_VIEWS
  where view_name IN ( ''ALL_INDEXES'', ''ALL_TABLES'')
  ) AS CONTACTS
  from dual 
 ') from dual
;

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <CONTACTS>
   <CONTACTS_ROW>
    <CONTACT_NAME>ALBERT EINSTEIN</CONTACT_NAME>
   </CONTACTS_ROW>
  </CONTACTS>
 </ROW>
</ROWSET>

所以当只有游标内有游标时,问题就出现了。

有人对此有解决方法吗?

【问题讨论】:

  • 请求有两个不同之处,只有第二个是真正需要的,但它对结果没有任何改变......
  • 你的两个光标是不同的对象; distinct 不会因为它们包含相同的行而同时看到它们吗?
  • @Alex Poole 也许这就是两个游标可以被视为两个不同对象的原因,无论如何,在 OO 中,两个不同的对象可以“相等”。

标签: sql oracle cursor expression distinct


【解决方案1】:

我认为你需要不同的输出,如下所示

<?xml version="1.0"?>
<ROWSET>
 <ROW>
  <CONTACTS>
   <CONTACTS_ROW>
    <CONTACT_NAME>ALBERT EINSTEIN</CONTACT_NAME>
    <INVOICE_NUMBER>123456</INVOICE_NUMBER>
    <INVOICE_AMOUNT>10000</INVOICE_AMOUNT>
    <INVOICE_CURRENCY>EUR</INVOICE_CURRENCY>
   </CONTACTS_ROW>
  </CONTACTS>
 </ROW>
</ROWSET>

为此不需要第二个光标。你可以像下面这样实现

select dbms_xmlgen.getxml('
select 
cursor (
  select 
    distinct 
    ''ALBERT EINSTEIN'' CONTACT_NAME 
    , 123456 INVOICE_NUMBER, 10000 INVOICE_AMOUNT, ''EUR'' INVOICE_CURRENCY 
  from 
  ALL_VIEWS
  where view_name IN ( ''ALL_INDEXES'', ''ALL_TABLES'')
  ) AS CONTACTS
  from dual 
 ') from dual
;

因为distint 在这种情况下是不同的。因此不需要子光标。这里distinct 将删除它自己的子查询中的所有记录。

【讨论】:

  • 对于某些需求,这是一种可能的解决方法,但我的报告有两个组,这意味着使用两个层次结构(联系人和发票),所以不确定我是否可以使用扁平结构。而且游标内游标的问题依然存在; XML 具有树状结构,通过将 XML 扁平化,就好像根本没有 XML,只有一个 flaf 文本文件;
  • 经过测试:它不起作用,因为一个联系人可以有多个发票,因此 XML 应该是两个级别才能正确呈现
【解决方案2】:

我也遇到了同样的情况,一段时间后我意识到如果我在sub cursor 使用 ORDER BYclause 那么它不会给出 DISTINCT 价值观。 使用您的 sub cursor 而不添加 ORDER BY clause。它肯定会给 DISTINCT

【讨论】:

  • 您好,感谢您的回答,但实际上我没有使用 order by 子句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多