ORA-01438: value larger than specified precision allows for this column - sql

We get sometimes the following error from our partner's database:
<i>ORA-01438: value larger than specified precision allows for this column</i>
The full response looks like the following:
<?xml version="1.0" encoding="windows-1251"?>
<response>
<status_code></status_code>
<error_text>ORA-01438: value larger than specified precision allows for this column ORA-06512: at "UMAIN.PAY_NET_V1_PKG", line 176 ORA-06512: at line 1</error_text>
<pay_id>5592988</pay_id>
<time_stamp></time_stamp>
</response>
What can be the cause for this error?

The number you are trying to store is too big for the field. Look at the SCALE and PRECISION. The difference between the two is the number of digits ahead of the decimal place that you can store.
select cast (10 as number(1,2)) from dual
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
select cast (15.33 as number(3,2)) from dual
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
Anything at the lower end gets truncated (silently)
select cast (5.33333333 as number(3,2)) from dual;
CAST(5.33333333ASNUMBER(3,2))
-----------------------------
5.33

The error seems not to be one of a character field, but more of a numeric one. (If it were a string problem like WW mentioned, you'd get a 'value too big' or something similar.) Probably you are using more digits than are allowed, e.g. 1,000000001 in a column defined as number (10,2).
Look at the source code as WW mentioned to figure out what column may be causing the problem. Then check the data if possible that is being used there.

Further to previous answers, you should note that a column defined as VARCHARS(10) will store 10 bytes, not 10 characters unless you define it as VARCHAR2(10 CHAR)
[The OP's question seems to be number related... this is just in case anyone else has a similar issue]

This indicates you are trying to put something too big into a column. For example, you have a VARCHAR2(10) column and you are putting in 11 characters. Same thing with number.
This is happening at line 176 of package UMAIN. You would need to go and have a look at that to see what it is up to. Hopefully you can look it up in your source control (or from user_source). Later versions of Oracle report this error better, telling you which column and what value.

FYI:
Numeric field size violations will give
ORA-01438: value larger than specified precision allowed for this column
VARCHAR2 field length violations will give
ORA-12899: value too large for column...
Oracle makes a distinction between the data types of the column based on the error code and message.

One issue I've had, and it was horribly tricky, was that the OCI call to describe a column attributes behaves diffrently depending on Oracle versions. Describing a simple NUMBER column created without any prec or scale returns differenlty on 9i, 1Og and 11g

From http://ora-01438.ora-code.com/ (the definitive resource outside of Oracle Support):
ORA-01438: value larger than specified precision allowed for this column
Cause: When inserting or updating records, a numeric value was entered that exceeded the precision defined for the column.
Action: Enter a value that complies with the numeric column's precision, or use the MODIFY option with the ALTER TABLE command to expand the precision.
http://ora-06512.ora-code.com/:
ORA-06512: at stringline string
Cause: Backtrace message as the stack is unwound by unhandled exceptions.
Action: Fix the problem causing the exception or write an exception handler for this condition. Or you may need to contact your application administrator or DBA.

It might be a good practice to define variables like below:
v_departmentid departments.department_id%TYPE;
NOT like below:
v_departmentid NUMBER(4)

It is also possible to get this error code, if you are using PHP and bound integer variables (oci_bind_by_name with SQLT_INT).
If you try to insert NULL via the bound variable, then you get this error or sometimes the value 2 is inserted (which is even more worse).
To solve this issue, you must bind the variable as string (SQLT_CHR) with fixed length instead. Before inserting NULL must be converted into an empty string (equals to NULL in Oracle) and all other integer values must be converted into its string representation.

Related

I have an issue trying to UNION All in SQL Server 2008

I am having to create a second header line and am using the first record of the Query to do this. I am using a UNION All to create this header record and the second part of the UNION to extract the Data required.
I have one issue on one column.
,'Active Energy kWh'
UNION ALL
,SUM(cast(invc.UNITS as Decimal (15,0)))
Each side are 11 lines before and after the Union and I have tried all sorts of combinations but it always results in an error message.
The above gives me "Error converting data type varchar to numeric."
Any help would be much appreciated.
The error message indicates that one of your values in the INVC table UNITS column is non-numeric. I would hazard a guess that it's either a string (VARCHAR or similar) column or something else - and one of the values has ended up in a state where it cannot be parsed.
Unfortunately there is no way other than checking small ranges of the table to gradually locate the 'bad' row (i.e. Try running the query for a few million rows at a time, then reducing the number until you home in on the bad data). SQL 2014 if you can get a database restored to it has the TRY_CONVERT function which will permit conversions to fail, enabling a more direct check - but you'll need to play with this on another system
(I'm assuming that an upgrade to 2014 for this feature is out of the question - your best bet is likely just looking for the bad row).
The problem is that you are trying to mix header information with data information in a single query.
Obviously, all your header columns will be strings. But not all your data columns will be strings, and SQL Server is unhappy when you mix data types this way.
What you are doing is equivalent to this:
select 'header1' as col1 -- string
union all
select 123.5 -- decimal
The above query produces the following error:
Error converting data type varchar to numeric.
...which makes sense, because you are trying to mix both a string (the header) with a decimal field.
So you have 2 options:
Remove the header columns from your query, and deal with header information outside your query.
Accept the fact that you'll need to convert the data type of every column to a string type. So when you have numeric data, you'll need to cast the column to varchar(n) explicitly.
In your case, it would mean adding the cast like this:
,'Active Energy kWh'
UNION ALL
,CAST(SUM(cast(invc.UNITS as Decimal (15,0))) AS VARCHAR(50)) -- Change 50 to appropriate value for your case
EDIT: Based on comment feedback, changed the cast to varchar to have an explicit length (varchar(n)) to avoid relying on the default length, which may or may not be long enough. OP knows the data, so OP needs to pick the right length.

Insert data via SSIS package and different datatypes

I have a table with a column1 nvarchar(50) null. I want to insert this into a more 'tight' table with a nvarchar(30) not null. My idea was to insert a derived column task between source and destination task with this expression: Replace column1 = (DT_WSTR,30)Column1
I get the "truncation may occur error" and I am not allowed to insert the data into the new tighter table.
Also I am 100% sure that no values are over 30 characters in the column. Moreover I do not have the possibility to change the column data type in the source.
What is the best way to create the ETL process?
JotaBe recommended using a data conversion transformation. Yes, that is another way to achieve the same thing, but it will also error out if truncation occurs. Your way should work (I tried it), provided the input data really is less than 30 characters.
You could modify your derived column expression to
(DT_WSTR,30)Substring([Column1], 1, 30)
Consider changing the truncation error disposition of the Derived Column component within your Data Flow. By default, a truncation will cause the Derived Column component to fail. You can configure the component to ignore or redirect rows which are causing a truncation error.
To do this, open the Derived Column Transformation editor and click the 'Configure Error Output...' button in the bottom-left of the dialog. From here, change the setting in the 'Truncation' column for any applicable columns as required.
Be aware that any data which is truncated for columns ignoring failure will not be reported by SSIS during execution. It sounds like you've already done this, but it's important to be sure you've analysed your data as it currently stands and taken into consideration any possible future changes to the nature of the data before disabling truncation reporting.
To do so you must use a Data Conversion Transformation, which allows to change the data type from the original nvarchar(50) to the desired nvarchar(30).
You'll get a new column with the required data type.
Of course, you can decide what to do in case of error: truncation, by configuring this component.
UPDATE
As there are people who have downvoted this answer, let's add 3 more comments:
this solution is checked and works. Create a table with a nvarchar(50) column, a new table with a nvarchar(30) column, add a data flow that uses a data conversion transform and it works witout a glitch. Please, chek it, I guarantee. Besides, as the OP states "Also I am 100% sure that no values are over 30 characters in the column" in his case there will be no truncation problems. However, I recommend treating the possible errors, just in case they happen.
from MSDN: "a package can perform the following types of data conversions: ... Set the column length of string data"
from MSDN: "If the length of an output column of string data is shorter than the length of its corresponding input column, the output data is truncated."

Oracle Error, moving data between databases

I am moving some data between two databases and have had much success, but then I encountered a problem doing the same kind of query that I've been doing.
The query:
INSERT INTO INTERNET.WEBSECURITY#crmtest SELECT * FROM INTERNET.WEBSECURITY;
The Error:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
Any ideas on what this might be?
You are trying to assign a value to a plsql variable which is not big enough or it has greater size than the column data type.
In addition: Assign/insert a non-numeric value to a numeric variable/column.
Probably your table columns are a bit different in datatypes and sizes. I do not see any variables in your example.

Strange PostgreSQL "value too long for type character varying(500)"

I have a Postgres schema which looks like:
The problem is that whenever I save text longer than 500 characters in the description column I get the error:
value too long for type character varying(500)
In the documentation for Postgres it says type text can have unlimited characters.
I'm using postgresql-9.1.
This table has been generated using Django 1.4 and the field type in the model is TextField, if that helps explain the problem further.
Any ideas as why this is happening and what I can do to fix it?
By specifying the column as VARCHAR(500) you've set an explicit 500 character limit. You might not have done this yourself explicitly, but Django has done it for you somewhere. Telling you where is hard when you haven't shown your model, the full error text, or the query that produced the error.
If you don't want one, use an unqualified VARCHAR, or use the TEXT type.
varchar and text are limited in length only by the system limits on column size - about 1GB - and by your memory. However, adding a length-qualifier to varchar sets a smaller limit manually. All of the following are largely equivalent:
column_name VARCHAR(500)
column_name VARCHAR CHECK (length(column_name) <= 500)
column_name TEXT CHECK (length(column_name) <= 500)
The only differences are in how database metadata is reported and which SQLSTATE is raised when the constraint is violated.
The length constraint is not generally obeyed in prepared statement parameters, function calls, etc, as shown:
regress=> \x
Expanded display is on.
regress=> PREPARE t2(varchar(500)) AS SELECT $1;
PREPARE
regress=> EXECUTE t2( repeat('x',601) );
-[ RECORD 1 ]-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
?column? | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
and in explicit casts it result in truncation:
regress=> SELECT repeat('x',501)::varchar(1);
-[ RECORD 1 ]
repeat | x
so I think you are using a VARCHAR(500) column, and you're looking at the wrong table or wrong instance of the database.
Character varying is different than text. Try running
ALTER TABLE product_product ALTER COLUMN code TYPE text;
That will change the column type to text, which is limited to some very large amount of data (you would probably never actually hit it.)
We had this same issue. We solved it adding 'length' to entity attribute definition:
#Column(columnDefinition="text", length=10485760)
private String configFileXml = "";
My problem was that I had Data in Table , So PostgreSQL don't allow me to Make changes on my table !
change it to bigger value !
I had the same problem. For my case, I went to pgAdmin>Schemas>Tables>blog_post and then arrow click to 'Colums' then found the colum, character varing(25). right click and then properties, click 'Definition. Finally I saw 'Length/Precision'. I changed 25 to 50. That's it. All good.
Once again, you need to change the size of your colum. go to pgAdmin>Schemas>Tables>(your app_model name)>Colums>(the colum you have problem)>Definition>Length
Change the size bigger. That's it!!!
Good luck!
Adding to answer by Scot S here.
For Django ImageField or FileField,
adding max_length in the models.py worked for me.
img1 = models.ImageField(upload_to=user_directory_path,**max_length=500**)
In my case:
migrated a
CharField(max_length=1) to CharField(max_length=2)
then save some data.
Then I wanna migrate back
DB already have data like "sg" inside.
just temporarily make them shorter will fix this error
Note if you have django-simple-history installed. got there and change/delete data as well
The error log didn't show what table/field, but the varying(1) indicate where you should go.

SQL - Numeric data type with leading zeros

I need to store Medicare APC codes. I believe the format requires 4 numbers. Leading zeros are relevant. Is there any way to store this data type with verification? How should I store this data (varchar(4), int)?
This kind of issue, storing zero leading numbers that need to be treated as Numeric values on some scenarios (i.e. sorting) and as textual values in others (i.e. addresses) is always a pain and there is no one answer that is best for all users. At my company we have a database that stores numbers as text for codes (not Medicare APC codes) and we must pad them with zero’s so they will sort properly when used in an order operation.
Do not use a numeric data type for this because the item is not a true number but textual data that uses numeric characters. You will not be performing any calculations or aggregates on the codes and so the only benefit to storing them as a number would be to ensure proper sorting of the codes and that can be done with the code stored as text by padding it with zeros where needed. If you sue a numeric data type then any time the code is combined with other textual values you will have to explicitly convert it to CHAR/VARCHAR or let SQL Server do it since implicit conversions should always be avoided that means a lot of extra work for you and the query processor any time the code is used.
Assuming you decide to go with a textual data type the question then is should you use VARCHAR or CHAR and while many who have posted say VARCHAR I would suggest you go with CHAR set to a length of 4. WHY?
The VARCHAR data type is for textual data in which the size (the length or number of characters) is unknown in advance. For this Medicare code we know the length will always be at least 4 and possibly no more than 4 for the foreseeable future. SQL Server handles the storage of the data differently between CHAR and VARCHAR. SQL Server’s BOL (Books On Line) says :
Use CHAR when the size of the column data entries are consistent
Use VARCHAR when the size of the column data varies considerably.
I can’t say for certain this is true for SQL Server 2008 and up but for earlier versions, the use of a VARCHAR data type carries an extra overhead of 1 byte per row of data per column in a table that has a VARCHAR data type. If the data stored is always the same size and in your scenario it sounds like it is then this extra byte is a waste.
In the end it’s up to you as to whether you like CHAR or VARCHAR better but definitely don’t use a numeric data type to store a fixed length code.
That's not numeric data; it's textual data that happens to contain digits.
Use a VARCHAR.
I agree, using
CHAR(4)
for the check constraint use
check( APC_ODE LIKE '[0-9][0-9][0-9][0-9]' )
This will force a 4 digit number only to be accepted...
varchar(4)
optionally, you can still add a check constraint to ensure the data is numeric with leading zeros. This example will throw exceptions in Oracle. In other RDBMS, you could use regular expression checks:
alter table X add constraint C
check (cast(APC_CODE as int) = cast(APC_CODE as int))
If you are certain that the APC codes will always be numeric (that is if it wouldn't change in the near future), a better way would be to leave the database column as is, and handle the formatting (to include leading zeros) at places where you use this field values.
If you need leading 0s, then you must use a varchar or other string data type.
There are ways to format the output for leading 0s without compromising your actual data.
See this blog entry for an easy method.
CHAR(4) seems more appropriate to me (if I understood you right, and the code is always 4 digits).
What you want to use is a VARCHAR data type with a CHECK constraint, using LIKE with a pattern to check for numeric values.
in TSQL
check( isnumeric(APC_ODE) = 1)