0

我正在尝试使用 select 语句创建一个表。我想用来自 VIEW 的聚合值填充这个新表。以下是用于创建 VIEW 的代码,

  create or replace view FINAL_WEB_LOG
 as
 select SESSION_ID, 
        SESSION_DT, 
        C_IP, 
        CS_USER_AGENT,
        tab_to_string(CAST(COLLECT(web_link) AS t_varchar2_tab)) WEBLINKS
 from web_views_tab    
 group by C_IP, CS_USER_AGENT, SESSION_DT;

我想创建一个带有 WEBLINKS 和 SESSION_ID 的表,它是另一个表的序列。当我尝试从 VIEW(没有 SESSION_ID 的表)创建表时,出现以下错误,

SQL 错误:ORA-06502:PL/SQL:数字或值错误:字符串缓冲区太小

这与 Weblinks 字段有关,它确实具有更长的值。我现在能做些什么来解决这个错误?

更多关于聚合函数的信息可以在AskTom中找到

4

5 回答 5

1

如果结果大于 4000 字节,则使用 CLOB。

SQL> create table web_views_tab(SESSION_ID number, SESSION_DT date, C_IP varchar2(20), CS_USER_AGENT varchar2(10), web_link varchar2(100));

Table created.

SQL> insert into web_views_tab
  2  select rownum, trunc(sysdate), '127.0.0.1', 'Mozilla', 'http://foo.bar.com/asdakjdlkajdlkajsd/asdjaldjklja'
  3  from dual
  4  connect by level <= 3000;

3000 rows created.

SQL> CREATE OR REPLACE TYPE t_varchar2_tab AS TABLE OF VARCHAR2(4000);
  2  /

Type created.

SQL> CREATE OR REPLACE FUNCTION tab_to_string (p_varchar2_tab  IN  t_varchar2_tab,
  2                                            p_delimiter     IN  VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS
  3    l_string     VARCHAR2(32767);
  4  BEGIN
  5    FOR i IN p_varchar2_tab.FIRST .. p_varchar2_tab.LAST LOOP
  6      IF i != p_varchar2_tab.FIRST THEN
  7        l_string := l_string || p_delimiter;
  8      END IF;
  9      l_string := l_string || p_varchar2_tab(i);
 10    END LOOP;
 11    RETURN l_string;
 12  END tab_to_string;
 13  /

Function created.

SQL> create or replace view FINAL_WEB_LOG
  2   as
  3   select SESSION_DT,
  4          C_IP,
  5          CS_USER_AGENT,
  6          tab_to_string(CAST(COLLECT(web_link) AS t_varchar2_tab)) WEBLINKS
  7   from web_views_tab
  8   group by C_IP, CS_USER_AGENT, SESSION_DT;

View created.

SQL> select * from FINAL_WEB_LOG;
select * from FINAL_WEB_LOG
                          *
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "TEST.TAB_TO_STRING", line 9
ORA-06512: at line 1

所以我们将函数输出重新定义为 clob 并稍微改变函数:

SQL> CREATE OR REPLACE FUNCTION tab_to_string (p_varchar2_tab  IN  t_varchar2_tab,
  2                                            p_delimiter     IN  VARCHAR2 DEFAULT ',') RETURN clob IS
  3    l_string     clob;
  4  BEGIN
  5    dbms_lob.createtemporary(l_string, true, dbms_lob.call);
  6     dbms_lob.open(l_string, dbms_lob.lob_readwrite);
  7    FOR i IN p_varchar2_tab.FIRST .. p_varchar2_tab.LAST LOOP
  8      IF i != p_varchar2_tab.FIRST THEN
  9        dbms_lob.writeappend(l_string, length(p_delimiter), p_delimiter);
 10      END IF;
 11        dbms_lob.writeappend(l_string, length(p_varchar2_tab(i)), p_varchar2_tab(i));
 12    END LOOP;
 13     dbms_lob.close(l_string);
 14    RETURN l_string;
 15  END tab_to_string;
 16  /

Function created.

SQL>
SQL> select * from FINAL_WEB_LOG;

SESSION_D C_IP                 CS_USER_AG
--------- -------------------- ----------
WEBLINKS
--------------------------------------------------------------------------------
14-DEC-12 127.0.0.1            Mozilla
http://foo.bar.com/asdakjdlkajdlkajsd/asdjaldjklja,http://foo.bar.com/asdakjdlka
于 2012-12-14T16:19:58.907 回答
1

您的声明现在无效,或者您将列:C_IPCS_USER_AGENT按部分分组,例如:

create or replace view FINAL_WEB_LOG
 as
 select SESSION_ID, 
        SESSION_DT, 
        C_IP, 
        CS_USER_AGENT,
        tab_to_string(CAST(COLLECT(web_link) AS t_varchar2_tab)) WEBLINKS
 from web_views_tab    
 group by C_IP, CS_USER_AGENT, SESSION_DT, C_IP, CS_USER_AGENT, WEBLINKS;

或者您将这些更改为使用从一组返回一个值的函数,例如 COUNT()、AVG()、MAX()、MIN() 等,例如:

create or replace view FINAL_WEB_LOG
 as
 select SESSION_ID, 
        SESSION_DT, 
        COUNT(C_IP), 
        COUNT(CS_USER_AGENT),
        Count(tab_to_string(CAST(COLLECT(web_link) AS t_varchar2_tab))) WEBLINKS
 from web_views_tab    
 group by C_IP, CS_USER_AGENT, SESSION_DT;
于 2012-12-14T05:54:58.473 回答
1

您不能使用不属于GROUP BY子句或聚合函数未涵盖的列。因为不可能知道在这种情况下应该返回哪个值。

如果保证每个组都是唯一的 - 你可以用

MIN(SESSION_ID) SESSION_ID

但请记住,这样做不是一个好习惯:-)

于 2012-12-14T05:50:31.730 回答
1

您不能选择不在按功能分组的字段。您将几个具有不同 session_id 的字段分组。你觉得你可以怎么选?

于 2012-12-14T05:51:13.413 回答
1

也放入子句session_idGROUP BY您应该始终将所有非聚合函数列放在SELECT子句中的GROUP BY子句中。

于 2012-12-14T06:00:49.993 回答