Hello,
Running out of ideas how to fix this case. I am getting an error: Error converting data type varchar to numeric.
CASE
WHEN sopHdr.SOPTYPE = 4
THEN CONVERT(int,(sopHdr.DOCAMNT - inv.TaxTotal) - CONVERT(int, inv.CostTotal)) * - 1 * CONVERT(int,proj.UserText1) / 100.0
ELSE CONVERT(int,(sopHdr.DOCAMNT - inv.TaxTotal) - inv.CostTotal) * CONVERT(int,proj.UserText1) / 100.0
END
Please help.
Answer from dimablys on community.spiceworks.comHello,
Running out of ideas how to fix this case. I am getting an error: Error converting data type varchar to numeric.
CASE
WHEN sopHdr.SOPTYPE = 4
THEN CONVERT(int,(sopHdr.DOCAMNT - inv.TaxTotal) - CONVERT(int, inv.CostTotal)) * - 1 * CONVERT(int,proj.UserText1) / 100.0
ELSE CONVERT(int,(sopHdr.DOCAMNT - inv.TaxTotal) - inv.CostTotal) * CONVERT(int,proj.UserText1) / 100.0
END
Please help.
The usual cause for this is that you have some records where the field has no numeric equivalent and thus cannot be converted to integer.
I would go so far as to guess that this happens in the UserText1 field in your example.
SQL Server has a ISNUMERIC() function to test if a character field can be expressed as a number however it is not quite perfect since it also recognizes expressions so it is not exactly a good way to test for valid conversion to a number. The TRY_CONVERT function in MS SQL 2012 (and later) is a better method.
If you are using MS SQL 2008, you can try to write your own TryConvert function: Simulating TRY_CONVERT() in SQL Server 2008
Are you using MS SQL or MySQL ?
Assuming your first table is named A with a column named MyIntColumn of type int and your second table is named B with a column named MyNVarcharColumn of type nvarchar, you could do
From A
Inner Join B On A,MyIntColumn = Try_Cast(B.MyNVarcharColumn As int)
Tom
Hi All,
I faced the same issue whenever a maintenance job was done by Azure Managed Service. The strange thing is that I got this exception from my services, and it was only resolved after a restart.
What happened in between?
.net - "Error converting data type nvarchar to int" when executing Stored Procedure and reading return value - Stack Overflow
SQL Server : error converting data type varchar to numeric - Stack Overflow
sql - Conversion failed when converting the varchar value 'simple, ' to data type int - Stack Overflow
UPDATE - SQL Server : error converting data type varchar to int - Stack Overflow
Videos
Lining up your arguments with the parameters:
'insert' -> @type varchar(50)
'dsad' -> @Customer_ID int
'[email protected]' -> @Customer_Name varchar(50)
'pass' -> @Email varchar(50)
'9999900000' -> @Password varchar(50)
-> @Mobile varchar(50) = null
...you can see that 'dsad' has no way of being understood as an int. Maybe there's a problem elsewhere as well, but at the very least, the stored procedure is not being called correctly.
Update:
If your intent was to omit some arguments that aren't relevant in a certain case, you have to use named parameters; otherwise, arguments can only be applied in the same order the parameters appear:
exec customer_registrations
'insert',
@Customer_Name = 'dsad',
@Email = '[email protected]',
@Password = 'pass',
@Mobile = '9999900000';
Please pass null value in procedure while you insert the data in table. Run the procedure below way while inserting data in table. you should me manage all the parameter of procedure. you are not passed value of Customer_ID, so that's way error occur.
EXEC [dbo].[Customer_Registrations] 'insert',null,'ewcewc', '[email protected]', 'dewdwd', '9999999999'
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.
In order to avoid such error you could use CASE + ISNUMERIC to handle scenarios when you cannot convert to int.
Change
CONVERT(INT, CONVERT(VARCHAR(12), a.value))
To
CONVERT(INT,
CASE
WHEN IsNumeric(CONVERT(VARCHAR(12), a.value)) = 1 THEN CONVERT(VARCHAR(12),a.value)
ELSE 0 END)
Basically this is saying if you cannot convert me to int assign value of 0 (in my example)
Alternatively you can look at this article about creating a custom function that will check if a.value is number: http://www.tek-tips.com/faqs.cfm?fid=6423
If you are converting a varchar to int make sure you do not have decimal places.
For example, if you are converting a varchar field with value (12345.0) to an integer then you get this conversion error. In my case I had all my fields with .0 as ending so I used the following statement to globally fix the problem.
CONVERT(int, replace(FIELD_NAME,'.0',''))
This is likely (we can't see enough of the code or data to be sure) a common issue with database order of operations. You have varchar columns backing f.ID and i.ID that have mixed data in them: some values can convert to int, but some cannot. You are then using a WHERE clause or JOIN condition to limit the query to only include values that do convert safely to int.
The problem is databases do not and will NEVER promise to use the order of operations you expect. There are many cases where the database will deem it more efficient to do the data projections (ie: CONVERT() calls) earlier, and the filtering operations later. And when this happens there is very little you can do to convince the database it needs to change this.
Instead, use the TRY_CONVERT() function that will give a NULL result for the invalid rows without failing the whole query. Or, even better, define the schema in a way that doesn't mix data types.
The problem was in a Trigger on dbo.Test.
The problem appears to be that your stored procedure expects 8 parameters:
stp_customers_insert(@customerid int, @name varchar(50), @phone varchar(50),
@doorno varchar(50), @streetname varchar(50), @city varchar(50),
@state varchar(50), @zip int)
but you are only passing 7 parameters when you actually call the proc:
exec stp_customers_insert 'ram','674673932','122','5th cross','trichy','tamilnadu',620001
If you don't know or don't want to perform the duplicate check on the CustomerID, then you could slightly modify your call to just pass NULL:
exec stp_customers_insert NULL, 'ram','674673932','122','5th cross','trichy','tamilnadu',620001
As an aside, if the proc is not even inserting the CustomerID, and this field is auto increment, then I don't see the point of passing it. Instead, you might want to consider using a unique constraint to achieve the same.
exec stp_customers_insert 1,'ram','674673932','122','5thcross','trichy','tamilnadu',620001
You have to pass @customerid value in procedure parameters - then it will execute without error.
OK. I finally created a view that works:
SELECT TOP (100) PERCENT id, CAST(CASE WHEN IsNumeric(MyCol) = 1 THEN MyCol ELSE NULL END AS bigint) AS MyCol
FROM dbo.MyTable
WHERE (MyCol NOT LIKE '%[^0-9]%')
Thanks to AdaTheDev and CodeByMoonlight. I used your two answers to get to this. (Thanks to the other repliers too of course)
Now when I do joins with other bigint cols or do something like 'SELECT * FROM MyView where mycol=1' it returns the correct result with no errors. My guess is that the CAST in the query itself causes the query optimizer to not look at the original table as Christian Hayter said may be going on with the other views
Ideally, you want to try to avoid storing the data in this form - would be worth splitting the BIGINT data out in to a separate column for both performance and ease of querying.
However, you can do a JOIN like this example. Note, I'm not using ISNUMERIC() to determine if it's a valid BIGINT because that would validate incorrect values which would cause a conversion error (e.g. decimal numbers).
DECLARE @MyTable TABLE (MyCol VARCHAR(20))
DECLARE @OtherTable TABLE (Id BIGINT)
INSERT @MyTable VALUES ('1')
INSERT @MyTable VALUES ('Text')
INSERT @MyTable VALUES ('1 and some text')
INSERT @MyTable VALUES ('1.34')
INSERT @MyTable VALUES ('2')
INSERT @OtherTable VALUES (1)
INSERT @OtherTable VALUES (2)
INSERT @OtherTable VALUES (3)
SELECT *
FROM @MyTable m
JOIN @OtherTable o ON CAST(m.MyCol AS BIGINT) = o.Id
WHERE m.MyCol NOT LIKE '%[^0-9]%'
Update: The only way I can find to get it to work for having a WHERE clause for a specific integer value without doing another CAST() on the supposedly bigint column in the where clause too, is to use a user defined function:
CREATE FUNCTION [dbo].[fnBigIntRecordsOnly]()
RETURNS @Results TABLE (BigIntCol BIGINT)
AS
BEGIN
INSERT @Results
SELECT CAST(MyCol AS BIGINT)
FROM MyTable
WHERE MyCol NOT LIKE '%[^0-9]%'
RETURN
END
SELECT * FROM [dbo].[fnBigIntRecordsOnly]() WHERE BigIntCol = 1
I don't really think this is a great idea performance wise, but it's a solution
You'd need to determine exactly what character was in the original string. Hopefully you have a copy of the original somewhere. I'm guessing it wasn't actually a full stop even if it displayed as one. This query may help
declare @s table
(
col varchar(20) not null
);
insert @s(col) values ('2010'), ('2010. ');
;with Numbers as
(
select top(20)
rn = ROW_NUMBER() over (order by (select 1))
from sys.objects as o
)
select
s.col,
n.rn,
SUBSTRING(s.col, n.rn, 1),
ASCII(SUBSTRING(s.col, n.rn, 1)),
UNICODE(SUBSTRING(s.col, n.rn, 1))
from @s as s
cross apply Numbers as n
where n.rn < = DATALENGTH(s.col)
and s.col like '%2010%'
order by
s.col,
n.rn;
The CTE is just a quick numbers table statically sized to the column's declared width. It will return one row per possible character position in the input data.
The main query uses the CTE's output as an ordinal index to extract one character at a time.
LEN() in most SQL distributions do not include spaces. You would want to use something like DATALENGTH() for that.
https://stackoverflow.com/questions/1151693/len-vs-datalength-in-sql-server-2005
As for where the '.' and spaces came from, we would need more information like how is that field being populated? What app, directly via SQL, etc.
Also, it would be helpful to know what distribution you are using. I assumed SQL Server.
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';
It looks like you may have missed a field in your line to execute the stored procedure. I quickly copied the stored proc input values into a spreadsheet followed by the values in your test line that throws the error. Have a look, it looks like you're missing perhaps the Day value? After that is entered it should line everything up correctly. I marked up the first line that after a quick glance looks like it is causing the error (others lower will too though, until the missing value is fixed).

Basic debugging would be to check your parameters... And if we do that...
Exec usp_New_Program_4 21, --@MemberNumber int
3, --@TrainerID int
'2020-06-06', --@ProgramStartDate date
'2020-07-07', --@TrainerReviewDate date
'Y', --@Active char(1)
'Chest & Arms', --@Description varchar(50)
SCOPE_IDENTITY, --@Day varchar(10)
'Bench
Press', --@ProgramID int
'50kg Barbell', --@ExerciseType_1 varchar(30)
3, --@Equipment_1 varchar(30)
6, --@Sets_1 int
'Press Ups', --@Reps_1 int
'Floor Mat', --@ExerciseType_2 varchar(30)
3, --@Equipment_2 varchar(30)
15, --@Sets_2 int
'Bicep Curls', --@Reps_2 int
'15kg
Dumbells', --@ExerciseType_3 varchar(30)
3, --@Equipment_3 varchar(30)
6, --@Sets_3 int
'Tricep Extensions', --@Reps_3 int
'15kg Dumbells', --@ExerciseType_4 varchar(30)
3, --@Equipment_4 varchar(30)
6, --@Sets_4 int
SCOPE_IDENTITY --@Reps_4 int
Pretty clear now. The value 'Bench
Press' is not an int. Neither are 'Press Ups'
, 'Bicep Curls' or 'Tricep Extensions'.
This is why using the format EXEC PROC {Proc Name} @{Parameter Name} = {Parameter Value} is really important for any procedures that have more than 1 or 2 parameters; you don't make simple mistakes like missing a parameter out.
In this case, you clearly missed out a value for @Day (as I assume you wanted to pass SCOPE_IDENTITY for @ProgramID), and thus all your parameters after that are wrong. The SP still ran fine though, as your last parameter (@WorkoutID) has a default value, and so didn't "mind" being omitted.