I tried below query
DECLARE #Input INT = 300
DECLARE #Ouput TINYINT
SET #Ouput = #Input
SELECT #Ouput
While execute the above statement, I received the following error.
Arithmetic overflow error for data type tinyint, value = 300.
The input value exceeds the limit, so the error is displayed.
I tried another query
DECLARE #Input INT = 300
DECLARE #Ouput BIT
SET #Ouput = #Input
SELECT #Ouput
When I execute the statement, I really wondered, it doesn't show any error. If the input value <> 0 (negative or positive), the output value always 1.
Converting to bit promotes any nonzero value to 1.
Sqlserver have power or say try to convert value implicitly as your input and output type without using cast or convert function, if you not specify any.
When the conversion error comes in default logic or scenerio, it give the specific type cast error.
So your tiny int and int length is differ, 300 is not fit in tiny int. Tiny int allow max at 255 value
Here is implicit & explicit convertion chart
You receive Arithmetic overflow on setting int value to tinyint because the range of value of int is larger than tinyint (you know. "tiny"(in small voice)).
Anf if you use bit which only have a value of O or 1 , basic in Computer fundamentals , and I think the value you get is 1 because it has a value, if none, you'll get 0.
Related
I tried creating my third table of phone numbers, I wrote the following commands:
CREATE TABLE MYPHONE (EMPLOYEE_ID INT, PHONE_NUMBER INT)
INSERT INTO MYPHONE
VALUES (1 , 7894561230)
But when I tried executing this previous INSERT command, I got an error:
Msg 8115, Level 16, State 2, Line 46
Arithmetic overflow error converting expression to data type int.
An int probably isn't the best data type for a phone number - you don't need to do any arithmetic on phone numbers, so why use a numerical data type? Store it as a string (or varchar in SQL).
Also, if you did need to store a value as an int, 2,147,483,647 is the maximum - anything higher would "overflow", hence the error you're getting. A long (or bigint in SQL) would allow values up to 9,223,372,036,854,775,808.
Allowed range of INT datatype is -2,147,483,648 to 2,147,483,647
You can get more details on the allowed range here
You are trying to insert beyond that range. For phone number better choose VARCHAR data type. If you still want to go for number, in that case use BIGINT instead of INT.
Just come across an interesting one:
declare #test as int
set #test = 47
select #test * 4.333
returns 203.651
declare #test as int
set #test = 47
declare #out as int
set #out = (select #test * 4.333)
select #out
returns 203
declare #test as int
set #test = 47
declare #out as int
set #out = round((select #test * 4.333),0)
select #out
returns 204
Now I know why it does this. Its because there is an implicit conversion from decimal to int, therefore the decimal places need chopped off (hence 203), whereas if I round prior to the implicit conversion I get 204.
My question is why when SQL Server does an implicit conversion is it not also rounding? I know if I had a big number, and it needed stored in a small place, the first thing I'd do would be to round it so as to be as close to the original number as possible.
It just doesn't seem intuitive to me.
This got me reading and the answer seems to be distinctly unsatisfying, The earliest SQL reference I've been able to find (ANSI 92 available here) in section 4.4.1 Characteristics of numbers states that
Whenever an exact or approximate numeric value is assigned to a
data item or parameter representing an exact numeric value,
an approximation of its value that preserves leading significant
digits after rounding or truncating is represented in the data
type of the target. The value is converted to have the precision and
scale of the target. The choice of whether to truncate or round
is implementation-defined.
Which leaves it up to Microsoft which of the two they chose to implement for T-SQL and I assume for the sake of simplicity they chose truncation. From the wikipedia article on rounding it seems that this wasn't an uncommon decision back in the day.
It's interesting to note that, according to the documentation I found, only conversions to integers cause truncation, the others cause rounding. Although for some bizarre reason the conversion from money to integer appears to buck the trend as it's allowed to round.
From To Behaviour
numeric numeric Round
numeric int Truncate
numeric money Round
money int Round
money numeric Round
float int Truncate
float numeric Round
float datetime Round
datetime int Round
Table from here.
I load excel file into sql as varchar(max) and got that Scientific e value which now I try to convert into numeric as I need to do compare that value, and here I'm running into problem.
This is main question: How and to what type I can convert this to compare with whole integer value ?
On the pic You can see how this seen in Excel, even formatted to text it somehow still loaded into varchar(max) not like char string. This can be seen from my test code.
DECLARE #C VARCHAR(MAX) = '1.1001562717e+011', #Nc VARCHAR(MAX) = '110015627174';
SELECT #c, LEN(#c) LenC ,
ISNUMERIC(#c) NumYN
---, CAST(#c AS DECIMAL(38,2)) cDec ---CAST(#c AS NUMERIC) cNum --, CAST(#c AS BIGINT) cInt
WHERE #c LIKE '%[^0-9]%'
AND ISNUMERIC(#c) = 1
To start, ISNUMERIC is a terrible function, it does not give good results; it is often wrong. If you try ISNUMERIC('1.1001562717e+011') you'll notice that you get the value 1, however, CONVERT(numeric(13,1),'1.1001562717e+011') will produce an error. A far better function is TRY_CONVERT (or TRY_CAST), which returns NULL if the conversion fails for the specific data type: TRY_CONVERT(numeric(13,1),'1.1001562717e+011').
Being specific on the data type is actually important here, as ISNUMERIC could be (incorrectly) suggesting that the value could be converted to at least 1 of the numeric data types; but that doesn't mean all of them. For scientific data types the only data type you can convert to is a float/real:
SELECT TRY_CONVERT(numeric(13,1),'1.1001562717e+011') AS Numeric,
TRY_CONVERT(bigint,'1.1001562717e+011') AS int,
TRY_CONVERT(float,'1.1001562717e+011') AS float,
TRY_CONVERT(money,'1.1001562717e+011') AS money;
Notice that only float has a value here. As you want a numeric as the final value, then you'll need to CONVERT the value twice:
CONVERT(numeric(13,1),TRY_CONVERT(float,'1.1001562717e+011'))
I am looking to retrieve a value of the profit (FilmBoxOfficeDollar - FilmBudgetDollars) based on the Studio given as a parameter to the function.
USE Movies;
GO
CREATE FUNCTION fnmovieProfits(#StudioName nvarchar(255))
RETURNS int
AS
BEGIN
RETURN (SELECT SUM(FilmBoxOfficeDollars - FilmBudgetDollars)
FROM Film JOIN Studio
ON Film.FilmStudioID = Studio.StudioID
WHERE StudioName = #StudioName);
END;
GO
SELECT [dbo].[fnmovieProfits]('Dreamworks');
Whenever I run this through to pull the piece of data I get the following error:
Msg 8115, Level 16, State 2, Line 13
Arithmetic overflow error converting expression to data type int.
Any help would be much appreciated!
The problem you are experiencing is that you are overflowing the allowed value of a 32 bit number (INT); if you cast/convert to a 64 bit number (BIGINT) and return that datatype, the issue will be corrected. Proof of concept showing the issue:
DECLARE #BigNumber INT=2000000000
select CONVERT(BIGINT,#BigNumber) + CONVERT(BIGINT,#BigNumber) --returns 4,000,000,000
select (#BigNumber + #BigNumber) --errors with "Arithmetic overflow error converting expression to data type int."
BUT, do yourself a favor and use a view instead. Scalars like that are terrible for performance in reports. Scalar functions should never be used unless they are simply doing calculations based on input values (i.e. not hitting underlying, persisted data).
CREATE VIEW dbo.v_StudioProfits
AS
SELECT
StudioName,
SUM(CONVERT(BIGINT,FilmBoxOfficeDollars) - CONVERT(BIGINT,FilmBudgetDollars)) AS [Profit]
FROM Film
INNER JOIN Studio ON Film.FilmStudioID = Studio.StudioID
GROUP BY StudioName
GO
SELECT * FROM dbo.v_StudioProfits WHERE StudioName='Dreamworks'
Relevant reading on SQL Server datatypes. Specifically, integer datatypes.
Your sum is exceeding int range. You should define your return type as bigint:
CREATE FUNCTION fnmovieProfits(#StudioName nvarchar(255))
RETURNS bigint
AS.......
The maximum value you can return with int as a return type is 2147483647. Your sum is probably bigger than that.
One example of function that exceeds its return type:
CREATE FUNCTION testFunction()
RETURNS int
AS
BEGIN
RETURN (SELECT 2147483647 + 1);
END;
GO
SELECT [dbo].[testFunction]();
If you execute it you will get the following error:
Msg 8115, Level 16, State 2, Line 8
Arithmetic overflow error converting expression to data type int.
So the solution is just to increase your return type range by replacing int with bigint.
How I can format string with D in start and leading zeros for digits with length of less than four. E.g:
D1000 for 1000
D0100 for 100
I have tried to work with casting and stuff function, but it didn't work as I expected.
SELECT STUFF('D0000', LEN(#OperatingEndProc) - 2, 4, CAST((CAST(SUBSTRING(#OperatingEndProc, 2, 4) AS INT) + 1) AS VARCHAR(10)));
adding 10000 to the value will cause the number to have have extra zeros first, then casting it as varchar and only using the last 4 will ignore the added 10000. This require that all numbers are between 0 and 9999
declare #value int = 100
select 'D' + right(cast(#value + 10000 as varchar(5)), 4)
This illustration board can come in handy when you wanna get the proper casting practices..
This shows all explicit and implicit data type conversions that are
allowed for SQL Server system-supplied data types. These include xml,
bigint, and sql_variant. There is no implicit conversion on assignment
from the sql_variant data type, but there is implicit conversion to
sql_variant
You can download it here http://www.microsoft.com/en-us/download/details.aspx?id=35834