Fix target length and truncation errors
The target database refuses a value because it does not fit the column: Oracle answers ORA-12899: value too large for column, SQL Server answers String or binary data would be truncated. The value is not always longer in characters. Text from an IBM i can grow in bytes when it reaches a UTF-8 target, and a column sized in bytes then fills up before it reaches its character count. This guide shows how to name the column, measure what it must hold, widen it, and size new target columns so that the error does not come back.
In this guide
You will learn how to find the table and the column behind the error, measure the longest value in characters and in bytes, widen the column on Oracle and on SQL Server, size the columns of a table that Gluesync creates, why IBM i text grows when it becomes UTF-8, what BYTE and CHAR mean in an Oracle column, and how to recognise the one truncation error that is not about the column at all.
Quick information
Goal |
Stop a length or truncation error on the target and size the columns so that it does not return |
Audience |
Gluesync administrators and database administrators |
Level |
Intermediate |
Time required |
About 30 minutes, plus the time of the |
Area |
Control Plane → pipeline → entity → Compare DDL, and Field mapping → Length |
Applies to |
Gluesync 2.3 |
Before you begin
Make sure that:
-
You can open the pipeline in the Control Plane and read the Notifications and alerts;
-
You can run SQL on the target database, for example with Query Studio, and you may change the table (
ALTER TABLE); -
You know the source and the target database type. This guide covers Oracle and SQL Server targets, and IBM i as a source of text that grows in bytes.
|
The sizes, defaults and caps in this guide come from the way Gluesync builds the |
Guide steps
UI
-
Open the entity that is in Error and read the message. On Oracle it names the column and gives the two sizes. On SQL Server 2019 and later it names the table, the column and the value that did not fit. Older SQL Server versions give only the text
String or binary data would be truncatedwithout the column; -
If the message does not name the column, select Compare DDL on the entity detail page. The source
CREATE TABLEis on the left and the target on the right: the column in error is the one that is shorter on the target; -
Write down the table, the column, the length on the source and the length on the target.
The page Prepare a SQL Server target shows the banner Target write failed and the notification String or binary data found truncated that name the column on a SQL Server target.
SQL
Do this on the target, because the rows that failed are not there yet. On the source, a check such as WHERE LENGTH(col) > 70 on an IBM i CHAR(70) column never finds a row: a fixed-length column always has its declared length, blanks included.
-
Widen the column to a generous value first (the next step shows how), so that the entity can write the rows that failed;
-
When the entity is Active again, measure the longest value in characters and in bytes.
Oracle:
SELECT MAX(LENGTH(line_text)) AS chars, MAX(LENGTHB(line_text)) AS bytes FROM <schema>.<table>;SQL Server:
SELECT MAX(LEN(note)) AS chars, MAX(DATALENGTH(note)) AS bytes FROM <schema>.<table>; -
Choose the final length from the larger of the two numbers that your column type counts (bytes for
VARCHAR2(n BYTE)andvarchar(n), characters forVARCHAR2(n CHAR)and, in UTF-16 units, fornvarchar(n)), and add room to grow.
SQL
Run the statement on the target, in a maintenance window if the table is large.
Oracle, sized in characters so that the limit follows the text and not the encoding:
ALTER TABLE <schema>.<table> MODIFY (line_text VARCHAR2(70 CHAR));
Oracle, sized in bytes:
ALTER TABLE <schema>.<table> MODIFY (line_text VARCHAR2(140 BYTE));
SQL Server:
ALTER TABLE <schema>.<table> ALTER COLUMN note varchar(300) NULL;
Then look at the entity in the Control Plane. On SQL Server the entity retries by itself and writes the rows that waited, with no restart. If an entity stays in Error after the ALTER TABLE, stop it and start it again with Where it stopped, so that it continues from its last checkpoint. Do not use Now: it skips the changes made while the entity was stopped (see Find and fix row differences).
|
Do not change the length in the Field mapping dialog of an entity that already runs just to follow an |
If you cannot widen the column, shorten the value in transit with a UDF (there is no built-in function that cuts text), or filter the long rows out with data filters.
UI
Do this before you confirm the Create table statement, so that the first long value does not fail weeks later.
-
In the Field mapping dialog, open the Target type and Length of every text column and compare them with the table in How Gluesync sizes the columns it creates;
-
For a column that holds accents, Chinese or other non-ASCII text, give the target a length in characters (
VARCHAR2(n CHAR)on Oracle) or a Unicode type (nvarcharon SQL Server), or multiply a byte length by the growth of your text (see IBM i text grows when it becomes UTF-8); -
For a column of unknown or very large length, choose
nvarcharwith Length-1on SQL Server (MAX); -
Read the generated
CREATE TABLE, edit it when a length is not right, and confirm.
IBM i text grows when it becomes UTF-8
An IBM i CHAR(n) or VARCHAR(n) column with a single-byte EBCDIC CCSID (for example 37 or 280) holds up to n characters, one byte each. Gluesync converts every character value to Unicode text, as described in AS/400 to MS SQL Server: character encoding Q&A. The target database then stores that text in its own encoding. When the target is UTF-8 and the column counts bytes, the same text can take more bytes than it took on the IBM i:
| Character | EBCDIC single-byte CCSID | UTF-8 |
|---|---|---|
Letters and digits of ASCII |
1 byte |
1 byte |
Accented letters such as |
1 byte |
2 bytes |
Euro sign, in the CCSIDs that have it |
1 byte |
3 bytes |
Chinese, Japanese and Korean ideographs |
2 bytes, in a double-byte CCSID |
3 bytes |
Emoji |
not in the CCSID |
4 bytes |
A 70-character text that has two accented letters needs 72 bytes in UTF-8. In a VARCHAR2(70) column sized in bytes it fails with ORA-12899: value too large for column … (actual: 72, maximum: 70), although the text has 70 characters and the source column is CHAR(70). The same happens on SQL Server for a varchar(n) column with a UTF-8 collation, where each é takes two bytes.
Check the encoding of your target:
-- Oracle
SELECT parameter, value FROM nls_database_parameters
WHERE parameter IN ('NLS_CHARACTERSET', 'NLS_LENGTH_SEMANTICS');
-- SQL Server
SELECT DATABASEPROPERTYEX(DB_NAME(), 'Collation') AS collation;
A character set such as AL32UTF8 stores text in UTF-8. A single-byte character set or a non-UTF-8 collation stores a Western accented letter in one byte, and replaces a character that its code page does not have (see the Q&A page above).
Fix it as in the steps: size the column in characters, or in more bytes than characters. For Chinese text, plan for 3 bytes per ideograph.
ORA-12899: value too large for column
What you see. The entity is in Error and the log has ORA-12899: value too large for column "<schema>"."<table>"."<column>" (actual: 72, maximum: 70), for example in the line Error writing transaction on target for entity … java.sql.BatchUpdateException: ORA-12899. Oracle gives the size of the value (actual) and the size of the column (maximum), in the unit of the column.
Why it happens. The value is larger than the column. Three cases are usual:
-
The target column is narrower than the source column;
-
The column is declared in bytes (
VARCHAR2(70 BYTE)) and the text has more bytes than characters, see IBM i text grows when it becomes UTF-8; -
The table was created by Gluesync and the column took the default of the database. The
CREATE TABLEthat Gluesync generates writesVARCHAR2(70), with noBYTEand noCHAR, so the column follows the parameterNLS_LENGTH_SEMANTICSof the database. That parameter isBYTEunless your database administrator changed it.
What to do.
-
Read the declared unit and sizes of the column:
SELECT column_name, data_type, data_length, char_length, char_used FROM all_tab_columns WHERE owner = '<SCHEMA>' AND table_name = '<TABLE>' AND data_type LIKE '%CHAR%' ORDER BY column_id;char_usedisBfor a column in bytes andCfor a column in characters;data_lengthis in bytes andchar_lengthin characters; -
Widen the column as in the step Widen the target column, in characters or in more bytes. Oracle limits a
VARCHAR2to 4000 bytes unless the database usesMAX_STRING_SIZE=EXTENDED, whichever unit you choose; -
For the tables that Gluesync creates next, edit the length in the Create table statement, see the step Size the columns of a table that Gluesync creates.
Check that it is fixed. The entity is Active, and SELECT MAX(LENGTHB(<column>)) FROM <table> is not larger than data_length of the column.
SQL Server: String or binary data would be truncated (errors 2628 and 8152)
What you see. The entity is in Error with a TargetWritingException and the message String or binary data would be truncated. SQL Server returns it as error 8152 on older versions and compatibility levels, with no table and no column. SQL Server 2019 and later return error 2628, String or binary data would be truncated in table '<table>', column '<column>'. Truncated value: '<value>'., which names the column.
Why it happens. A value is larger than its target column, in bytes for varchar(n) and varbinary(n), in UTF-16 code units for nvarchar(n). Ten é do not fit in a varchar(10) column with a UTF-8 collation. Ten emoji do not fit in an nvarchar(10) column.
What to do.
-
Find the column, as in the first step. With error 8152, compare the widths with Compare DDL and with the queries of Prepare a SQL Server target;
-
Widen the column as in the third step. The entity retries by itself;
-
If the column is already as wide as the source column, read the next section.
Check that it is fixed. The entity returns to Active and SELECT MAX(DATALENGTH(<column>)) FROM <table> is not larger than the byte length of the column.
The error appears although the target column is wide enough
What you see. String or binary data would be truncated on a SQL Server target, on a binary or varbinary column (for example a source CHAR … FOR BIT DATA column that holds hexadecimal data), with a target column that is exactly as long as the source column. The first step finds no difference between the two lengths.
Why it happens. When Gluesync writes a large batch of changes to SQL Server, it stages the rows in a temporary table. In some releases that table declared its binary and varbinary columns without a length, and SQL Server created them one byte long, so every longer value was rejected. The data and the target column were correct. The temporary table now declares the length of the column.
What to do.
-
Update Gluesync to the latest release of your line (2.2 or 2.3) from Platform updates, and check the version shown in the Control Plane;
-
Do not reload the table. The entity continues from the batch that it was stuck on;
-
Start the entity if it is stopped.
Check that it is fixed. The entity returns to Active and the binary column has the same value as on the source. A row count that is larger on the target than on the source is a different problem: see Choose keys for tables without a primary key.
How Gluesync sizes the columns it creates
For an Oracle or a SQL Server target, Gluesync copies the length of the source column into the CREATE TABLE. It does not enlarge the length for UTF-8. When the source length is unknown or larger than the limit of the target type, it uses the limit:
| Target | Text column | Length used |
|---|---|---|
Oracle |
|
Source length, at most 2000 |
Oracle |
|
Source length, at most 32767. The unit follows |
SQL Server |
|
Source length, at most 8000. Unknown length: |
SQL Server |
|
Source length, at most 4000. Unknown length: |
SQL Server |
|
Source length. Unknown length ( |
Two consequences follow. A source column longer than the cap of the target type is created at the cap: for example a source VARCHAR(10000) becomes varchar(8000) on SQL Server, so set the length to MAX before you confirm. And a text column in characters on the source becomes a column of the same number, in bytes or in characters according to the target, so a UTF-8 target needs the check of the section IBM i text grows when it becomes UTF-8.
Troubleshooting
| Problem | Possible cause | What to do |
|---|---|---|
|
The target column counts bytes and the text has accented or non-Latin characters |
Change the column to |
The check |
A |
Measure on the target with |
|
SQL Server 2017 or earlier, or an older compatibility level (error 8152) |
Compare the widths with Compare DDL and the queries of the SQL Server guide |
The same error on a |
The temporary table of an older release had binary columns of one byte |
Update Gluesync, see The error appears although the target column is wide enough |
After the |
The entity did not retry yet, or the error comes from another column |
Wait a few seconds, then stop and start it with Where it stopped, and read the new message |
The created table has |
The source length is above the cap of the target type |
Set the length to |
Oracle refuses the |
A length above 4000 bytes on a database without |
Choose 4000 or less, or ask the database administrator to enable the extended size |
|
The target column or the collation has no code point for it |
Use a Unicode type ( |
Informix target, snapshot: |
The dbspace of the table uses a 4 KB page size |
In the reported case the error ended after the page size was raised to 16 KB. Ask your Informix administrator to check the page size of the dbspace of the table |
Related guides
Contact MOLO17 Support if you need assistance with a length or truncation error.