So we have PIVOT keyword in Oracle /SQL Serverwhen you convert rows to columns.
Not in DB2, I want to convert row results and concatenate them into a column, dynamically, as in, I do not know the number of rows I might get, they might vary.
Eg
table x
COL1 COL2
ABC 10
ABC 20
ABC 30
I want to display this as
COL1 COL2
ABC 10,20,30
But the count of records might vary so I cannot use case.
Want to do this for queries of many tables not a particular query; a function or most preferably in the select query itself.
If you are using Db2 LUW 11.1.4.4 release, you might be able to workaround using sysibm.json_array function:
VALUES JSON_ARRAY(SELECT DEPTNO FROM DEPT);
1
-------------------------------
["F22","G22","H22","I22","J22"]
you can then stored the json_array in a character based column, varchar, clob.
For longer strings.
select substr(xmlserialize(
xmlquery('$L/text()' passing XMLAGG(xmlelement(name "a", ','||colname)) as "L")
as clob(1m)
), 2)
from syscat.columns;
Let me illustrate what I need with an example.
Suppose my table has two columns, the first column is the primary key and the second column is a CLOB.
Suppose the clob column in my table holds the following data:
Method_name : Test_method_124
Grading: As Specified
Grading Time Period: 2016 Fall
I want to find the string which is after 'Grading Time Period'. The output of my query should be the primary key (that is, the first column of the table) and '2016 Fall'
Use DBMS_LOB functions to work with CLOBs. instr() returns the starting offset of the searched pattern in a CLOB. substr() returns a substring, which is n characters from the given offset in a CLOB. Find out more
SQL> select id,
2 dbms_lob.substr(txt, 30, dbms_lob.instr(txt,'Grading Time Period')+21) as snippet
3 from t23
4 where dbms_lob.instr(txt, 'Grading Time Period') > 0:
ID SNIPPET
---------- ----------
1 2016 Fall
SQL>
This is a poor way to store data. Really this should be properly normalised into table columns. But even XML or JSON would be a better way of handling this. Look at it this way. If you wanted to extract the Grading how would you specify the buffer to ensure you grabbed only As Specified? It's possible but it's gnarly.
I am running the following query. But getting ORA-12899. Altough the length of string am trying to insert is 30.
INSERT INTO TABLE1 SELECT * FROM temp_Table1 where LENGTH(column1)=30;
SQL Error: ORA-12899:value too large for column "TABLE1"."column1" (actual: 31, maximum: 30)
select column1 from temp_Table1 where LENGTH(column1)=30;
Testing - HLC/TC Design Corre
Desc temp_Table1
column1 VARCHAR2(30)
Desc Table1
column1 VARCHAR2(30)
You're seeing the difference between character and byte length semantics:
You must specify a maximum length for a VARCHAR2 column. This maximum must be at least 1 byte, although the actual string stored is permitted to be a zero-length string (''). You can use the CHAR qualifier, for example VARCHAR2(10 CHAR), to give the maximum length in characters instead of bytes. A character is technically a code point of the database character set. You can use the BYTE qualifier, for example VARCHAR2(10 BYTE), to explicitly give the maximum length in bytes. If no explicit qualifier is included in a column or attribute definition when a database object with this column or attribute is created, then the length semantics are determined by the value of the NLS_LENGTH_SEMANTICS parameter of the session creating the object.
If your session is using byte semantics then the column in your table will default to that:
select value from nls_session_parameters where parameter = 'NLS_LENGTH_SEMANTICS';
VALUE
----------------------------------------
BYTE
create table t42(text varchar2(5));
Table T42 created.
select char_used from user_tab_columns where table_name = 'T42' and column_name = 'TEXT';
C
-
B
That is the same as explicitly doing:
create table t42(text varchar2(5 byte));
If your source data is five characters but includes any multibyte characters then the number of bytes will exceed five:
insert into t42 (text) values ('Hello');
1 row inserted.
insert into t42 (text) values ('Señor');
SQL Error: ORA-12899: value too large for column "SCHEMA"."T42"."TEXT" (actual: 6, maximum: 5)
Which is what you're seeing. When you insert the values from your other table you are filter on the length of the values, but length() counts characters rather than bytes. There is a lengthb() function that does count bytes. If you check the byte length of the 30-character value you're selecting you'll see it is in fact 31 bytes, so one of those characters is multibyte.
with t42 (text) as (
select 'Hello' from dual
union all select 'Señor' from dual
union all select 'Testing - HLC/TC Design Corre' from dual
)
select text, length(text) as chars, lengthb(text) as bytes, dump(text, 16) as hex
from t42;
TEXT CHARS BYTES HEX
------------------------------- ----- ----- ----------------------------------------------------------------------------------------------------------
Hello 5 5 Typ=1 Len=5: 48,65,6c,6c,6f
Señor 5 6 Typ=1 Len=6: 53,65,c3,b1,6f,72
Testing - HLC/TC Design Corre 30 31 Typ=1 Len=31: 54,65,73,74,69,6e,67,c2,a0,20,2d,20,48,4c,43,2f,54,43,20,44,65,73,69,67,6e,20,43,6f,72,72,65
From the dump() values you can see that after Testing (54,65,73,74,69,6e,67) and before the space and dash (20,2d) you have c2,a0, which is the UTF-8 multibyte non-breaking space character. (You often see that, along with curly quotes and other non-ASCII-range characters, in text that has been copied from,. say, a Word document).
You can either change your insert to filter on LENGTHB(column1)=30 (which will exclude the row you currently find), or change your column definition to 30 characters instead of 30 bytes:
drop table t42;
Table T42 dropped.
create table t42(text varchar2(5 char));
Table T42 created.
select char_used from user_tab_columns where table_name = 'T42' and column_name = 'TEXT';
C
-
C
insert into t42 (text) values ('Hello');
1 row inserted.
insert into t42 (text) values ('Señor');
1 row inserted.
Or replace any unexpected multibyte characters with single-byte equivalents, if that's possible and makes sense for your data; in this case a normal space might work, but with any substitution you are destroying information that might actually be important.
Try to change your table like
ALTER TABLE1 MODIFY column1 VARCHAR2(30 CHAR)
The error states that your column1 can store maximum of 30 characters and you are passing more than 30 characters in it which results in the error.
You can also refer this article: Oracle Database - Bytes or Characters for VARCHAR2 and CHAR
ORA-12899
Often times, as our companies grow and evolve in response to an
expansion in the form of client-base, staff, profit or markets, the
data associated with this growth will also change. Data systems like
Oracle have the innate ability to remain fairly flexible in regards to
working with this variance in information. Still, even the most
versatile database systems require maintenance and refining in the
face of increased data traffic. This work is essential to
accommodating any constraints on memory or necessary redefinitions of
parameters. The ORA-12899 error is representative of an instance in
which either an uptick in data or a user error is forcing Oracle to
stall during its requested action.
THE PROBLEM
The ORA-12899 is an Oracle error that occurs when the value entered
into the column string is too large. What this means is that an
attempt was made by the user to update or insert a column with a value
that is too wide for the destination column. The name of a particular
column will be given and the actual width of the value, as well as the
maximum width permitted for the column, will be associated with that.
As mentioned, the value can be given in the form of characters. In the
event that the width is reported in characters, this will mean that
character length semantics are operating for the column. Otherwise the
width will be reported in bytes. Essentially, this error results from
trying to push through a value, or set of values, that exceed the
specified maximum width of the column. So, how does a user correct
this type of error?
THE SOLUTION
To begin, open up the OERR utility. The user will require the full
ORA-12899 message to receive the proper feedback on the error. This
will provide more information on the error and allow further
investigation. Typically, the error can come from one of three
sources. The first source is the SQL statements that have been
generated. Checking source and destination column data types to
discover whether they are compatible with current formats is the
second source. Lastly, the user can look at the destination column
width – where the value is being assigned – to make sure it is large
enough to accommodate the maximum value that the user anticipates
assigning. Let us now turn to an example that corrects ORA-12899.
Suppose the user has created the following table:
CREATE TABLE Clients(
ClientID varchar2(9) PRIMARY KEY,
Client_Contact varchar2(40) NOT NULL,
Address varchar(20) NOT NULL,
Zip varchar2(5) NOT NULL,
Client_Number varchar2(11) NOT NULL)
The user then attempts to issue an INSERT VALUES statement that looks
something like this:
INSERT INTO Clients VALUES(
727546345,
‘Roger Holcomb’,
‘—Benjamin Road Syracuse’,
‘-----‘, 05307623754)
The user might try to run the statement from here, but will receive
the following error message:
Error starting at line 7 in command: INSERT INTO Clients
VALUES(727546345, ‘Ricky Galorey’, ‘18 Benjamin Road Syracuse’,
‘13208’, 05307623754) Error report: SQL Error: ORA-12899: value too
large for column “ORGANIZATIONS”. “MARKET”. “ADDRESS”(actual: 25,
maximum: 20) 12899. 00000 – “value too large for column %s (actual:
%s, maximum: %s)”
This error statement indicates that the variable ‘Address’ cannot hold
more than twenty characters as that would exceed the width of the
column parameter. When we look back at the address value (’18 Benjamin
Road Syracuse’) we can see that the total number of characters (25)
exceeds the maximum number allowed for the width of the column. To
correct this, the user can change the VARCHAR2 for address to an
amount that can accommodate the typical address length that their
company would input.
The above answer original URL
Due to different NLS settings in the target table database it might require more bytes in the target.
Try altering the table as
alter Table1 modify column1 varchar2(30 char)
It seems SQLPLUS shows nulls and empty strings for CLOBs in a way that I wasn't expecting.
Try the following in SQLPLUS (I'm using Oracle 10g Server). Create a table with a CLOB, and insert null, empty clob, and what I think of as an empty string:
create table tableA (field1 number, field2 clob);
insert into tableA values (1, null);
insert into tableA values (2, empty_clob());
insert into tableA values (3, '');
OK, lets do some queries, but first we need to tell SQLPLUS to show nulls clearly for us:
set null {NULL}
For the following query, I would have expected only row 1 returned, but it returns 2:
select * from tableA where field2 is null;
field1 field 2
-----------------------
1 {NULL}
3 {NULL}
Hmm, so '' is stored as a null in a CLOB?
Ok, so based on that result, I would now expect the following query to return all 3 rows but show {NULL} in rows 1 and 3 only. However I get this result:
select * from tableA;
field1 field 2
-----------------------
1 {NULL}
2 {NULL}
3 {NULL}
This is confusing. I thought there were only 2 nulls, even though I originally expected 1. So what's going on here? Does set null not work for CLOBs, and if so what should I use instead?
I'm actually trying to solve a different problem with null CLOB values, but this confusing behaviour has had me running rings for a while, so I'd like to understand this before I continue.
Thanks in advance
Boz
Oracle does not distinguish between NULL and an empty string. This is a well-known violation or SQL standards.
This is the reason of default string type being VARCHAR2 and not VARCHAR.
In all currently released versions they are the same, but VARCHAR is not recommended for use. This is because VARCHAR is supposed to distinguish between NULL and an empty string, while VARCHAR2, not being described in the standards, is not.
I think it's something to do with the way SQL*Plus handles empty strings and null values.
empty_clob() does not create a NULL value, but a CLOB of length zero.
Which is proven by the fact that row 2 is is not returned when you query for rows where field2 is null.
With my JDBC tool I can highlight columns that are null with a different color, and there the row with the empty_clob() is not highlighted whereas the other two are.
So I'd say it's a wrong handling of the set null option in SQL*Plus. With the following statement you will see the difference:
select field1,
nvl(field2, 'THIS IS NULL')
from tableA;
For me this displays:
field1 field 2
-----------------------
1 THIS IS NULL
2
3 THIS IS NULL
It would be interesting to see what is really in row 2. It may not truly be null as according to the documentation (see below) empty_clob() will return a initialized clob locate that does not have data (somewhat unclear on the null issue).
When executing SQL statements in SQL query tools though Oracle tends to implicitly convert CLOB's to strings which are cut off at some arbitrary length.
Purpose
EMPTY_BLOB and EMPTY_CLOB return an empty LOB locator that can be used to initialize a LOB variable or, in an INSERT or UPDATE statement, to initialize a LOB column or attribute to EMPTY. EMPTY means that the LOB is initialized, but not populated with data.
I have a column which is of type nvarchar(max). How do I find the length of the string (or the number of bytes) for the column for each row in the table?
SELECT LEN(columnName) AS MyLength
FROM myTable
If you want to find out the max there should be a way for you to get the schema of the table. Normally you can do something like SHOW COLUMNS in SQL or a DESCRIBE style command. In a mysql shell that can be shortened to:
desc tablename;
Then if you want to determine the length of a string there is normally a function like LENGTH (for bytes) or CHAR_LENGTH (for characters).
SELECT *, LENGTH(fieldname) AS len FROM tablename
SELECT LEN(columnName) AS MyLength FROM myTable
I used this query for my table. It displays the size of each row in a particular column.
I need that field name size maximum it allow the characters.