The problem is obvious -- you have a string and you are treating it as a number. There are three possible reasons.
The first is an explicit conversion where the string is converted to a number. This should be easy to find. You can replace the explicit conversion with try_convert() in SQL Server 2012+.
The second is not much harder. The + operator is used both for addition and string concatenation. It often causes this type of problem. All numeric arguments need to be converted to strings. Or, change all code that does concatenation to use the CONCAT() function -- the arguments are automatically converted to strings.
The third is implicit conversion for numeric operations. If you have any other operations (or function calls) that require numeric values, then SQL Server will implicitly convert the values to numbers. This can be very hard to find. Try to write code that does not rely on implicit conversions.
Note: Trying to filter out bad values using a WHERE clause (even in a subquery or CTE) does not work.
The problem is obvious -- you have a string and you are treating it as a number. There are three possible reasons.
The first is an explicit conversion where the string is converted to a number. This should be easy to find. You can replace the explicit conversion with try_convert() in SQL Server 2012+.
The second is not much harder. The + operator is used both for addition and string concatenation. It often causes this type of problem. All numeric arguments need to be converted to strings. Or, change all code that does concatenation to use the CONCAT() function -- the arguments are automatically converted to strings.
The third is implicit conversion for numeric operations. If you have any other operations (or function calls) that require numeric values, then SQL Server will implicitly convert the values to numbers. This can be very hard to find. Try to write code that does not rely on implicit conversions.
Note: Trying to filter out bad values using a WHERE clause (even in a subquery or CTE) does not work.
Found the error, sharing my answer hoping someone is facing the same problem. This is where the error was
CASE [Category].[ID]
WHEN '1' THEN [Category].[Name]
WHEN '2' THEN [Category].[Weight]
END
Here [Category].[Name] is string and [Category].[Weight] is real, trying different data types inside the same CASE clause, so to solve this all what I had to do is split this condition, like this
CASE [Category].[ID]
WHEN '1' THEN [Category].[Name]
END,
CASE [Category].[ID]
WHEN '2' THEN [Category].[Weight]
END
Hope this helps
Converting varchar to real causing CONVERT errors unexpectedly -- RELOAD of stored procedure with no changes fixed problem.
Error converting data type varchar to real
Error converting data type varchar to numeric
Error converting data type varchar to numeric issue – SQLServerCentral Forums
Videos
I tried a lot of things to fix it, and no success.
I have a field called MASTER_BOL_NUMBER . According to documentation it is CHAR.

I see that inside it has only blanks and numbers

When I try to CAST( MASTER_BOL_NUMBER as numeric)
I am getting an error “Error converting data type varchar to numeric.”
I tried also smth like that
CAST( IIF(MASTER_BOL_NUMBER='',0,MASTER_BOL_NUMBER) as numeric)
and this
CAST( IIF(MASTER_BOL_NUMBER IS NULL,0,MASTER_BOL_NUMBER) as numeric)
Also no success, I really don’t understand why I am getting this error because usually CAST or CONVERT fix this data type issues.
Does someone else know what may help but for those functions?
Try this.
CAST( IIF(ISNULL(MASTER_BOL_NUMBER,’0’)=‘’,’0’,MASTER_BOL_NUMBER) as numeric)
drop table #Population
CREATE TABLE #Population
(
AcctNo varchar(25) NULL, DateOfBirth varchar(50) NULL, First\_Name varchar(50) NULL, Last\_Name varchar(50) NULL, Address1 varchar(50) NULL, Address2 varchar(50) NULL, AddressCity varchar(25) NULL, AddressState varchar(5) NULL, AddressZip varchar(50) NULL, Listdate datetime NULL, Campaign\_Name varchar(50) NULL, Email\_Address varchar(100) NULL, Pathcoreid varchar(25) NULL, Scrub varchar (500) default 'Available', Detail1 varchar(30) NULL, Detail2 varchar(30) NULL, Detail3 varchar(30) NULL, Detail4 varchar(30) NULL, Channel varchar(50) NULL, Opendate varchar(50) NULL, SSN varchar(50) NULL, Gender varchar(50) NULL, Assets decimal(10,2)
)
INSERT INTO #Population
(
AcctNo,
DateOfBirth,
First_Name,
Last_Name,
Address1,
Address2,
AddressCity,
AddressState,
AddressZip,
Email_Address,
Pathcoreid,
Opendate,
SSN,
Gender,
Assets
)
SELECT DISTINCT
AD.AcctDateID,
AP.DateOfBirth,
AP.first_name,
AP.last_name,
CASE
WHEN ISNUMERIC(AF.Assets) = 1 THEN CONVERT(decimal(10,2), AF.Assets)
ELSE 0 -- Handle non-numeric values with a default
END AS Assets,
AP.SSN,
AP.AddressLine1,
AP.AddressLine12,
AP.AddressCity,
AP.AddressState,
AP.gender,
AP.OpenDate,
AP.AddressZipCd,
AD.PathCoreID,
AP.email
FROM
Accounts_Profile AS AP
INNER JOIN
[dbo].[Accounts_Financial] AS AF ON AP.AcctNo = AF.AcctNo
INNER JOIN
[dbo].[Accounts_Date] AS AD ON AD.AcctNo = AP.AcctNo
WHERE
AP.channel = 'saving';
SQL Server 2012 and Later
Just use Try_Convert instead:
TRY_CONVERT takes the value passed to it and tries to convert it to the specified data_type. If the cast succeeds, TRY_CONVERT returns the value as the specified data_type; if an error occurs, null is returned. However if you request a conversion that is explicitly not permitted, then TRY_CONVERT fails with an error.
Read more about Try_Convert.
SQL Server 2008 and Earlier
The traditional way of handling this is by guarding every expression with a case statement so that no matter when it is evaluated, it will not create an error, even if it logically seems that the CASE statement should not be needed. Something like this:
SELECT
Account_Code =
Convert(
bigint, -- only gives up to 18 digits, so use decimal(20, 0) if you must
CASE
WHEN X.Account_Code LIKE '%[^0-9]%' THEN NULL
ELSE X.Account_Code
END
),
A.Descr
FROM dbo.Account A
WHERE
Convert(
bigint,
CASE
WHEN X.Account_Code LIKE '%[^0-9]%' THEN NULL
ELSE X.Account_Code
END
) BETWEEN 503100 AND 503205
However, I like using strategies such as this with SQL Server 2005 and up:
SELECT
Account_Code = Convert(bigint, X.Account_Code),
A.Descr
FROM
dbo.Account A
OUTER APPLY (
SELECT A.Account_Code WHERE A.Account_Code NOT LIKE '%[^0-9]%'
) X
WHERE
Convert(bigint, X.Account_Code) BETWEEN 503100 AND 503205
What this does is strategically switch the Account_Code values to NULL inside of the X table when they are not numeric. I initially used CROSS APPLY but as Mikael Eriksson so aptly pointed out, this resulted in the same error because the query parser ran into the exact same problem of optimizing away my attempt to force the expression order (predicate pushdown defeated it). By switching to OUTER APPLY it changed the actual meaning of the operation so that X.Account_Code could contain NULL values within the outer query, thus requiring proper evaluation order.
You may be interested to read Erland Sommarskog's Microsoft Connect request about this evaluation order issue. He in fact calls it a bug.
There are additional issues here but I can't address them now.
P.S. I had a brainstorm today. An alternate to the "traditional way" that I suggested is a SELECT expression with an outer reference, which also works in SQL Server 2000. (I've noticed that since learning CROSS/OUTER APPLY I've improved my query capability with older SQL Server versions, too--as I am getting more versatile with the "outer reference" capabilities of SELECT, ON, and WHERE clauses!)
SELECT
Account_Code =
Convert(
bigint,
(SELECT A.AccountCode WHERE A.Account_Code NOT LIKE '%[^0-9]%')
),
A.Descr
FROM dbo.Account A
WHERE
Convert(
bigint,
(SELECT A.AccountCode WHERE A.Account_Code NOT LIKE '%[^0-9]%')
) BETWEEN 503100 AND 503205
It's a lot shorter than the CASE statement.
There's no guarantee that SQL Server won't attempt to perform the CONVERT to numeric(20,0) before it runs the filter in the WHERE clause.
And, even if it did, ISNUMERIC isn't adequate, since it recognises £ and 1d4 as being numeric, neither of which can be converted to numeric(20,0).(*)
Split it into two separate queries, the first of which filters the results and places them in a temp table or table variable, the second of which performs the conversion. (Subqueries and CTEs are inadequate to prevent the optimizer from attempting the conversion before the filter)
For your filter, probably use account_code not like '%[^0-9]%' instead of ISNUMERIC.
(*) ISNUMERIC answers the question that no-one (so far as I'm aware) has ever wanted to ask - "can this string be converted to any of the numeric datatypes - I don't care which?" - when obviously, what most people want to ask is "can this string be converted to x?" where x is a specific target datatype.