我正在尝试使用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
答案 0 :(得分:1)
您不能使用不属于GROUP BY
子句但未被聚合函数覆盖的列。因为在这种情况下不可能知道应该返回哪个值。
如果保证每组都是唯一的 - 你可以用
欺骗数据库MIN(SESSION_ID) SESSION_ID
但请记住,这样做不是一个好习惯: - )
答案 1 :(得分:1)
您无法选择不按功能分组的字段。您使用不同的session_id对少数字段进行分组。您认为如何选择一个?
答案 2 :(得分:1)
您的陈述现在无效,您可以按以下方式将列C_IP
,CS_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;
答案 3 :(得分:1)
将session_id
放在GROUP BY
子句中。您应该始终将SELECT
子句中的所有非聚合函数列放在GROUP BY
子句中。
答案 4 :(得分:1)
如果结果是>则使用CLOB。 4000字节。
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