2

I'm getting the following error when trying to concatenate column values in Oracle 11.1g:

ORA-06502: PL/SQL: numeric or value error: character string buffer too small

I first looked at SQL Query to concatenate column values from multiple rows in Oracle to see if I could use some of the solutions provided - but had no success.

My data looks like the following:

Table A

PID

A
B
C

Table B

PID   SEQ       NOTE_FRAGMENT

A     9999      This is the start of the note
A     9998      and this is a continuation of that note.
A     9997      Finally, this is the last part of the note for PID A.
B     9999      Note data for PID B.
C     9999      Yes
C     9998      we can 
C     9997      do 
C     9996      this work!

My query is as follows:

SELECT 
A.PID,
B.SEQ,
wm_concat(B.NOTE_FRAGMENT)
FROM A 
inner join b on A.PID = B.PID
group by A.PID, B.SEQ
order by B.SEQ

Again, I'm trying to combine all the notes for a given PID in order from greatest to least seq number. I also have a hunch that my ordering is off since I'm pretty rusty on my SQL, but I had trouble finding how since I was first getting stuck on the buffer issue.

Community
  • 1
  • 1
sager89
  • 940
  • 1
  • 12
  • 25
  • Would the concatenated string exceed 4000 bytes? Is there a reason that you are using the undocumented `wm_concat` function? Rather than using, say, the `listagg` analytic function from the question you linked to? Or a user-defined aggregate function? – Justin Cave Aug 24 '14 at 02:08
  • I'm using oracle 11.1 which is why I'm using wm_concat, and I believe that example using listagg was for 11.2 as I couldn't get it to work for me. I'm not sure if the concatenated string could exceed 4000 bytes, but I think it's certainly possible. – sager89 Aug 24 '14 at 02:52
  • If the result can be more than 4000 bytes, you can't use `wm_concat` (you also couldn't use `listagg` even if you were using 11.2). Can you create a custom aggregate function and use that? – Justin Cave Aug 24 '14 at 03:01
  • Looks like many of my results are over 4000. Not too sure how to write custom aggregate functions, so I'm thinking I might write a program to string them together after exporting to csv. – sager89 Aug 24 '14 at 03:47
  • @JustinCave How do you know the maximum allowable size for an aggregation operation? Is it dependent on the column type that is being aggregated (in this case I just realized it's varchar2(1500)) or does it come from the maximums from Oracle's documentation http://docs.oracle.com/cd/B28359_01/server.111/b28320/limits001.htm#i287903 where it says varchar2 is 4000 bytes? – sager89 Aug 24 '14 at 15:11
  • You can find the solution of your problem it [here](https://dba.stackexchange.com/questions/103398/modify-listagg-query-for-10g) – Saddam Meshaal Sep 10 '18 at 14:40

1 Answers1

0

I am guessing that B.SEQ is not in the group by for your query (otherwise, according to your data, you would be concatenating one row).

So, start by measuring the length of the resulting string:

SELECT A.PID, SUM(LENGTH(B.NOTE_FRAGMENT))
FROM A inner join
     b
     on A.PID = B.PID
group by A.PID
order by 3 DESC;

If the largest value is over 4000, then you can't put the results into a string.

By the way, in Oracle 11g, I would recommend listagg() instead of wm_concat().

EDIT:

Actually, Oracle is pretty powerful, so you can actually do what you want:

SELECT A.PID,
       listagg(CASE WHEN CLEN < 3500 THEN B.NOTE_FRAGMENT END), ' ') WITHIN GROUP (ORDER BY B.SEQ)
FROM (SELECT A.PID, B.SEQ,
             SUM(LENGTH(B.NOTE_FRAGMENT) + 1) OVER (PARTITION BY A.PID ORDER BY B.SEQ) as CLEN
      FROM A inner join
           b
           on A.PID = B.PID
     ) AB
GROUP BY A.PID
ORDER BY 3 DESC;

This measures the length and stops the concatenation before it gets too long.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • After trying this query, I got the following error: ORA-00923: FROM keyword not found where expected 00923. 00000 - "FROM keyword not found where expected" Do you know if this has to do with the version of Oracle used? Again, I'm using 11.1 – sager89 Aug 24 '14 at 03:12
  • @sager89 . . . There were a couple of typos in the query. – Gordon Linoff Aug 24 '14 at 03:15
  • Even without typos, it seems to be finding the error after the 'WITHIN' clause. Also, looks like the length of the largest note is 333750... with many other records well over 4000... Looks like I'll have to write a program to string these together outside of Oracle... – sager89 Aug 24 '14 at 03:46
  • @sager89 . . . Odd. The logic should only be taking notes that are well less than 4000 characters in cumulative length. – Gordon Linoff Aug 24 '14 at 04:11
  • Sorry, I was talking about the sql query that just gave the length. I was getting an error trying to run the query that actually returned the concatenated notes. The error keeps appearing after the "Within" clause saying that the "FROM keyword not found where expected" – sager89 Aug 24 '14 at 04:15
  • Hmmmm . . . Closer inspection reveals that `listagg()` is available in 11gR2. Is that the version you are using? If not, back to `wm_concat()`. – Gordon Linoff Aug 24 '14 at 04:17
  • Nope, sadly I'm using 11.1. Really wish I was on 11gR2 at this point :) – sager89 Aug 24 '14 at 04:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/59887/discussion-between-sager89-and-gordon-linoff). – sager89 Aug 24 '14 at 14:37