Меню

Conversion failed when converting the varchar value to data type int ошибка

I wrote the store procedure which should return the values like-

J1
J2
J3

I have table named Journal_Entry. When the row count of the table is 0, it gives the result J1 but as the row count increases it shows the error-

"Conversion failed when converting the varchar value 'J' to data type int."

#here the Voucher_No is the column for the result to be saved.

The code is like-

CREATE PROC [dbo].[getVoucherNo]
AS
BEGIN
    DECLARE @Prefix VARCHAR(10)='J'
    DECLARE @startFrom INT=1
    DECLARE @maxCode VARCHAR(100)
    DECLARE @sCode INT
    IF((SELECT COUNT(*) FROM dbo.Journal_Entry) > 0)
    BEGIN
        SELECT @maxCode = CAST(MAX(CAST(SUBSTRING(Voucher_No,LEN(@startFrom)+1,LEN(Voucher_No)- LEN(@Prefix)) AS INT)) AS varchar(100)) FROM dbo.Journal_Entry;
        SET @sCode=CAST(@maxCode AS INT)
        SELECT  @Prefix + LEN(CAST(@maxCode AS VARCHAR(10))+1) + CAST(@maxCode AS VARCHAR(100))
    END
    ELSE
    BEGIN
        SELECT(@Prefix + CAST(@startFrom AS VARCHAR)) 
    END

END

Devart's user avatar

Devart

118k22 gold badges162 silver badges184 bronze badges

asked Jul 10, 2013 at 10:14

naren's user avatar

4

The problem located on the following line

SELECT  @Prefix + LEN(CAST(@maxCode AS VARCHAR(10))+1) + CAST(@maxCode AS VARCHAR(100))

Use this instead

SELECT  @Prefix + CAST(LEN(CAST(@maxCode AS VARCHAR(10))+1) AS VARCHAR(100)) + CAST(@maxCode AS VARCHAR(100))

Full Code:

CREATE PROC [dbo].[getVoucherNo]

AS

BEGIN

    DECLARE @Prefix VARCHAR(10)='J'

    DECLARE @startFrom INT=1

    DECLARE @maxCode VARCHAR(100)

    DECLARE @sCode INT

    IF((SELECT COUNT(*) FROM dbo.Journal_Entry) > 0)
    BEGIN
        SELECT @maxCode = CAST(MAX(CAST(SUBSTRING(VoucharNo,LEN(@startFrom)+1,LEN(VoucharNo)- LEN(@Prefix)) AS INT))+1 AS varchar(100)) FROM dbo.Journal_Entry;
        SET @sCode=CAST(@maxCode AS INT)
        SELECT  @Prefix + CAST(LEN(CAST(@maxCode AS VARCHAR(10))+1) AS VARCHAR(100)) + CAST(@maxCode AS VARCHAR(100))
    END
    ELSE
    BEGIN
        SELECT(@Prefix + CAST(@startFrom AS VARCHAR)) 
    END
END

Mohammad Areeb Siddiqui's user avatar

answered Jul 10, 2013 at 11:31

Jaychand's user avatar

2

I got the same error message. In my case, it was due to not using quotes.

Although the column was supposed to have only numbers, it was a Varchar column, and one of the rows had a letter in it.

So I was doing this:

select * from mytable where myid = 1234

While I should be doing this:

select * from mytable where myid = '1234'

If the column had all numbers, the conversion would have worked, but not in this case.

answered Feb 11, 2014 at 14:03

live-love's user avatar

live-lovelive-love

46.1k22 gold badges227 silver badges196 bronze badges

Your problem seams to be located here:

SELECT @maxCode = CAST(MAX(CAST(SUBSTRING(Voucher_No,LEN(@startFrom)+1,LEN(Voucher_No)- LEN(@Prefix)) AS INT)) AS varchar(100)) FROM dbo.Journal_Entry;
SET @sCode=CAST(@maxCode AS INT)

As the error says, you’re casting a string that contains a letter ‘J’ to an INT which for obvious reasons is not possible.

Either fix SUBSTRING or don’t store the letter ‘J’ in the database and only prepend it when reading.

answered Jul 10, 2013 at 10:18

Jakub Konecki's user avatar

Jakub KoneckiJakub Konecki

45.3k7 gold badges87 silver badges126 bronze badges

The line

SELECT  @Prefix + LEN(CAST(@maxCode AS VARCHAR(10))+1) + CAST(@maxCode AS VARCHAR(100))

is wrong.

@Prefix is 'J' and LEN(...anything...) is an int, hence the type mismatch.


It seems to me, you actually want to do,

SELECT
        @maxCode = MAX(
            CAST(SUBSTRING(
                Voucher_No,
                @startFrom + 1,
                LEN(Voucher_No) - (@startFrom + 1)) AS INT)
    FROM
        dbo.Journal_Entry;

SELECT  @Prefix + CAST(@maxCode AS VARCHAR(10));

but, I couldn’t say. If you illustrated before and after data, it would help.

answered Jul 10, 2013 at 10:20

Jodrell's user avatar

JodrellJodrell

34.4k5 gold badges85 silver badges123 bronze badges

Try this one —

CREATE PROC [dbo].[getVoucherNo]
AS BEGIN

     DECLARE 
            @Prefix VARCHAR(10) = 'J'
          , @startFrom INT = 1
          , @maxCode VARCHAR(100)
          , @sCode INT

     IF EXISTS(
          SELECT 1 
          FROM dbo.Journal_Entry
     ) BEGIN

          SELECT @maxCode = CAST(MAX(CAST(SUBSTRING(Voucher_No,LEN(@startFrom)+1,ABS(LEN(Voucher_No)- LEN(@Prefix))) AS INT)) AS varchar(100)) 
          FROM dbo.Journal_Entry;

          SELECT @Prefix + 
               CAST(LEN(LEFT(@maxCode, 10) + 1) AS VARCHAR(10)) + -- !!! possible problem here
               CAST(@maxCode AS VARCHAR(100))

     END
     ELSE BEGIN

          SELECT (@Prefix + CAST(@startFrom AS VARCHAR)) 

     END

END

answered Jul 10, 2013 at 10:20

Devart's user avatar

DevartDevart

118k22 gold badges162 silver badges184 bronze badges

1

  • Remove From My Forums
  • Question

  • Dear All,

    When I am firing a below query  I am getting the error

    SELECT 
    Empcode,
    Date_of_Joining,
    LastWorkingDate,
    Tenure,
    CASE WHEN CAST( Tenure AS INTEGER) =1 THEN ‘THREE’ ELSE Tenure END TEN

    FROM #TEMP

    tenure I AM getting bu substracting lastworking date to date of joining

    Error:-

    Msg 245, Level 16, State 1, Line 1
    Conversion failed when converting the varchar value ‘THREE’ to data type int.

    Regards,

    Vipin jha


    Thankx & regards, Vipin jha MCP

    • Changed type

      Monday, January 7, 2013 4:41 PM
      Question rather than discussion

Answers

  • Try this,

    The problem is you are trying to mix int and varchar datatypes together.

    SELECT 
    Empcode,
    Date_of_Joining,
    LastWorkingDate,
    Tenure,
    CASE WHEN CAST( Tenure AS INTEGER) =1 THEN 'THREE' ELSE Convert(Varchar(100),Tenure) END TEN
    
    FROM #TEMP

    Regards
    satheesh

    • Proposed as answer by
      Kalman Toth
      Monday, January 7, 2013 6:40 PM
    • Marked as answer by
      Allen Li — MSFT
      Monday, January 14, 2013 5:59 AM

  • Try

    SELECT 
    Empcode,
    Date_of_Joining,
    LastWorkingDate,
    Tenure,
    CASE WHEN Tenure NOT LIKE '%[^0-9]%' then when CAST( Tenure AS INTEGER) =1 THEN 'THREE' 
    else cast(Tenure as varchar(20)) end
    ELSE cast(Tenure as varchar(20)) END As TEN


    For every expert, there is an equal and opposite expert. — Becker’s Law

    My blog

    • Proposed as answer by
      Kalman Toth
      Monday, January 7, 2013 6:40 PM
    • Marked as answer by
      Allen Li — MSFT
      Monday, January 14, 2013 5:59 AM

If you are seeing an error similar to “Conversion failed when converting the varchar value ‘something’ to data type int.”, I find the easiest method for identifying a solution to the problem is to analyze the data causing the error.

To illustrate how I identify bad data when making conversions, consider the environment setup below:

DECLARE @table TABLE (id VARCHAR(4));
INSERT INTO @table (id)
VALUES ('1' -- id - int
    )
     , ('NULL')
     , (NULL);

We have a simple table with a single column. The column type is a varchar(4) that allows NULL entries. We have inserted a 1, NULL, and the word “NULL”. Here’s what our table looks like:

-- Step 1, see what the values look like.
SELECT *
FROM   @table;

Your table and data set will probably be more complicated than our example table here. The methodology still remains true however to identifying our bad data. Let’s start by seeing the error our table produces.

-- Step 2, See how conversion errors out.
SELECT CAST(id AS INT)
FROM   @table;

Now to identify what is causing that problem, I’m going to use the TRY_CAST function wrapped in a CASE WHEN statement. I’ll persist this data set in memory with a CTE and then select the results filtered by the data sets giving me troubles.

-- Step 3, how do we find out what is causing the error?
; WITH cte AS (
	SELECT 
		CASE WHEN 
			TRY_CAST(id AS INT) IS NULL 
			THEN id 
			ELSE 'BadData' 
		END AS result 
	FROM @table
)
SELECT * FROM cte 
WHERE result <> 'BadData';

As we can see, it was the string “NULL” instead of the other NULL entry that was causing the conversion error. This is because the word “NULL” and a NULL entry are two very different things. I’m not going to dive too much into that in this post, but I do plan on discussing this topic later!

So what if I wanted to leave the bad data out of the equation and convert only the good data?

-- Step 4, convert only the good data.
; WITH cte AS (
	SELECT 
		CASE WHEN 
			TRY_CAST(id AS INT) IS NOT NULL 
			THEN id 
			ELSE 'BadData' 
		END AS result 
	FROM @table
)
SELECT 
	cast(result as INT) as 'ConvertedValue' 
FROM CTE 
WHERE result <> 'BadData'

The idea here is that when the TRY_CAST value IS NOT NULL, then we display the ID value. We are reversing the CASE WHEN piece here to identify the good data now so we can easily filter out the bad data. This allows us to filter the results and perform a CAST on the values. A similar effect could be achieved by attaching the CASE WHEN statement to the subqueries WHERE clause and also adding the result for BadData filter, thereby negating the CTE. This can potentially cause a massive performance problem, so use with caution.

The reason for the need to have the CASE WHEN in the WHERE clause or utilizing a CTE (or some other method to hold a result set) is due to the logical order of operations performed by SQL. SQL evaluates the following clauses in this order:

  1. FROM
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. ORDER BY

This means our query analyzes the WHERE clause first before the SELECT occurs. This means the below query would be invalid:

SELECT 
CASE WHEN 
			TRY_CAST(id AS INT) IS NOT NULL 
			THEN id 
			ELSE 'BadData' 
		END AS result 
FROM @table
WHERE result = 'BadData'

The column name and CASE WHEN function don’t even process before we begin to query the table variable and attempt a predicate filter on the column ‘result’. Here’s a valid example of filtering logic in the WHERE clause with a CASE WHEN.

SELECT 
CASE WHEN 
			TRY_CAST(id AS INT) IS NOT NULL 
			THEN id 
			ELSE 'BadData' 
		END AS result 
FROM @table
WHERE 
'BadData' <> CASE 
				WHEN 
				 TRY_CAST(id AS INT) IS NOT NULL 
				THEN id 
			ELSE 'BadData' 
		END

Again, this can have huge performance ramifications. In my experience, this generally can cause an index scan depending on your index setup. So as always, evaluate the situation and think critically about the route you want to take to solve the problem. Measure, tweak, record, compare, repeat.

Ideally, the best way to resolve the issue is to create constraints that force consistency and reliability in your data. The next best from there is going in and fixing your data sets periodically as issues appear.

I have added in a form for feedback, it would be very helpful if you would take a few minutes to fill this out. My goal is to adjust the content to best help others resolve their problems.

  • Remove From My Forums
  • Question

  • Hi, I am working on a report which is off of survey information and I am using dynamic pivot on multiple columns.

    I have questions like Did you use this parking tag for more than 250 hours? If yes specify number of hours.
    and the answers could be No, 302, 279, No and so on….

    All these answers are of varchar datatype and all this data comes from a partner application where we consume this data for internal reporting.

    When I am doing dynamic pivot I get the below error.

    Error: Conversion failed when converting the varchar value ‘No’ to data type int.

    Query

    DECLARE @Cols1 VARCHAR(MAX), @Cols0 VARCHAR(MAX), @Total VARCHAR(MAX), @SQL VARCHAR(MAX)
    
    SELECT @Cols1 = STUFF((SELECT ', ' + QUOTENAME(Question) FROM Question GROUP BY Question FOR XML PATH('')),1,2,'')  
    
    SELECT @Cols0 = (SELECT ', COALESCE(' + QUOTENAME(Question) + ',0) as ' + QUOTENAME(Question) FROM Question GROUP BY Question FOR XML PATH(''))
    
    SET @SQL = 'SELECT QID, QNAME' + @Cols0 + '
    FROM (SELECT QID, QNAME, ANSWERS, Question
    FROM Question) T
    PIVOT (MAX(ANSWERS) FOR Question IN ('+@Cols1+')) AS P'
     
    EXECUTE (@SQL)

    I am using SQL Server 2008 R2.

    Please guide me to resolve this.

    Thanks in advance……….


    Ione

Answers

  • create table questions (QID int, QNAME varchar(50), ANSWERS varchar(500),  Question varchar(50))
    
    Insert into questions values(1,'a','b','c'), (2,'a2','b2','c2') 
    
    DECLARE @Cols1 VARCHAR(MAX), @Cols0 VARCHAR(MAX), @Total VARCHAR(MAX), @SQL VARCHAR(MAX)
    
    SELECT @Cols1 = STUFF((SELECT ', ' + QUOTENAME(Question) FROM Questions GROUP BY Question FOR XML PATH('')),1,2,'')  
    
    SELECT @Cols0 = (SELECT ', COALESCE(' + QUOTENAME(Question) + ',''0'') as ' + QUOTENAME(Question) FROM Questions GROUP BY Question FOR XML PATH(''))
    
    SET @SQL = 'SELECT QID, QNAME' + @Cols0 + '
    FROM (SELECT QID, QNAME, ANSWERS, Question
    FROM Questions) T
    PIVOT (MAX(ANSWERS) FOR Question IN ('+@Cols1+')) AS P'
     
    EXECUTE (@SQL)
    
    
    drop table questions

    • Marked as answer by

      Monday, February 9, 2015 4:59 PM

Giff is almost right. The problem is that you’re trying to add a number to a string literal. Because of SQL’s type conversion rules, it tries to convert the string to a number in order to perform the addition.

You would need to convert the number to a string before concatenating it to the string literal:

SET @CUSTOMERIDS = 'AND VU_CRM_Customers.CustomerID = ' + CAST(@CustomerID As varchar(20))

But that’s not a good approach. Whilst you’re probably safe in this particular instance, since the parameters are either numbers or dates, using string concatenation to build a SQL query can leave you vulnerable to SQL Injection[^].

sp_executesql[^] gives you a much safer option: pass the parameters as parameters:

CREATE PROCEDURE SP_Customer(@FromDate date, @ToDate date, @AccessLevelCode nvarchar(30) = NULL, @UserID nvarchar(30) = NULL, @UserOrgBranchID int = NULL, @UserGroupID int = NULL, @CustomerID int = 0)
AS
BEGIN
DECLARE @SQL nvarchar(max), @params nvarchar(max);
DECLARE @AccessFilter nvarchar(max), @CustomerIDs nvarchar(max);

    SET NOCOUNT ON;
    SET @AccessFilter = dbo.fnGetAccessFilter(@AccessLevelCode, @UserID, @UserOrgBranchID, @UserGroupID);
    
    SET @CustomerIDs = CASE
        WHEN @CustomerID Is Null THEN N''
        ELSE N'AND VU_CRM_Customers.CustomerID = @CustomerID'
    END;

    SET @SQL = N'	
    DECLARE @Temp TABLE
    (
        [Row] INT,
        Customer NVARCHAR(MAX),
        CustomerID int,
        TransactionType NVARCHAR(MAX),
        VoucherDate smalldatetime,
        VoucherNo NVARCHAR(MAX),
        AccountingDate datetime,
        Amount numeric(18,3),
        Debit numeric(18,3),
        Credit numeric(18,3),        
        [OrgID] INT
    );
    
    INSERT INTO @Temp 
    SELECT 
        ROW_NUMBER() OVER(PARTITION BY Customer ORDER BY CreatedDate) AS Row, 
        * 
    FROM
        (
            SELECT 
                CASE 
                    WHEN ISNULL(ISNULL(Mobile,Phone),'''') = '''' THEN Customer 
                    ELSE CONCAT(Customer,''('',ISNULL(Mobile,Phone),'')'') 
                END AS Customer,
                ''Opening Balance'' AS TransactionType,
                AccountingDate AS VoucherDate,
                COALESCE(ACC_FinOpeningBalance.ReferenceNo, CONVERT(nvarchar,OpeningBalanceID)) AS VoucherNo,
                AccountingDate AS CreatedDate,
                CASE WHEN Dr > 0 THEN Dr ELSE Cr END AS Amount,
                Dr AS Debit,
                Cr AS Credit,
                ACC_FinOpeningBalance.OrgID
            FROM 
                ACC_FinOpeningBalance 
                INNER JOIN VU_CRM_Customers 
                ON ACC_FinOpeningBalance.SLGroupCode = ''C'' 
                AND ACC_FinOpeningBalance.SubledgerID = VU_CRM_Customers.CustomerID
            WHERE 
                ACC_FinOpeningBalance.CreatedBy' + @AccessFilter + @CustomerIDs + N'
            
            UNION
            
            SELECT 
                 CASE 
                     WHEN ISNULL(ISNULL(Mobile,Phone),'''')='''' THEN Customer 
                     ELSE CONCAT(Customer,''('',ISNULL(Mobile,Phone),'')'') 
                 END AS Customer,
                ''Advance'' AS TransactionType,
                 AdvanceDate AS VoucherDate,
                 COALESCE(ACC_AdvanceReceived.ReferenceNo, CONVERT(nvarchar,AdvanceReceivedID)) AS VoucherNo,
                 AdvanceDate AS CreatedDate,
                 NetReceivable AS Amount,
                 NetReceivable AS Debit,
                 0 AS Credit,
                 ACC_AdvanceReceived.OrgID 
            FROM 
                ACC_AdvanceReceived 
                INNER JOIN VU_CRM_Customers 
                ON ACC_AdvanceReceived.AccountID = VU_CRM_Customers.CustomerID
            WHERE 
                Customer IS NOT NULL
            AND 
                ACC_AdvanceReceived.CreatedBy' + @AccessFilter + @CustomerIDs + N'
        )
    ;
    
    SELECT 
        *,
        (M.OpeningBalance + M.Debit - M.Credit) AS ClosingBalance 
    FROM
        (
            SELECT 
                L.Row,
                L.Customer,
                L.TransactionType,
                L.VoucherDate,
                L.VoucherNo,
                L.AccountingDate,
                L.Amount,
                L.OrgID,
                ISNULL((SELECT SUM(Debit) - SUM(Credit) FROM @Temp AS O WHERE O.AccountingDate <= L.AccountingDate AND O.Customer = L.Customer AND O.Row < L.Row), 0) AS OpeningBalance,
                L.Debit,
                L.Credit 
            FROM 
                @Temp AS L 
            WHERE 
                L.AccountingDate  >= @FromDate 
            And 
                L.AccountingDate < @ToDate
        ) As M
    ;';
    
    SET @params = N'@FromDate date, @ToDate date, @CustomerID int';
    EXEC sp_executesql @SQL, @params, @FromDate = @FromDate, @ToDate = @ToDate, @CustomerID = @CustomerID;
    print @SQL;
END

NB: You can probably do something about the value returned from fnGetAccessFilter as well; but since I can’t see the code for that function, I can’t tell you.

NB2: Tidying up your dynamic query makes it obvious that you have several misplaced brackets. Once you’d fixed the conversion error, the next error would be a syntax error trying to execute your query. I think I’ve fixed it, but you should probably check.

NB3: Depending on which version of SQL Server you’re running, there is probably a much cleaner way to generate the running totals. If it’s 2012 or later, you can use the LAG function[^].

The Reason for this error is you are converting a varchar value to Int or Numeric or any Other datatype let us take a simple example 

select CAST(‘abc’ as int)

Msg 245, Level 16, State 1, Line 1

Conversion failed when converting the varchar value ‘abc’ to data type int.

what we are doing in above query is changing the nvarchar value to int which is not possible that why it throw the error.

While working with TSQL Coding if you are adding some string value with alphanumeric field  you could face the above problem if you have not written your query properly.

Take an Example where you want to show empidEmpsalary from employee table

for this we will create a table below 

create table Employee1_error1

(Empid int identity (1,1) ,EmpName nvarchar(50),EmpSalary float)

insert into Employee1_error1  values(‘Amit’,’5000′),(‘Sumit’,’6000′),(‘Raj’,’8000′),(‘vijay’,’9000′),(‘suresh’,’10000′)

select * from Employee1_error1 

now we want to display employee empidEmpsalary in same format we are concatenating the slash in between empidEmpsalary 

like  we want our result like 

EmpIdEmpsalary

 15000

 26000 and so on ……….

now run the below query 

select cast(empid+»+empsalary as varchar) from Employee1_error1

Msg 245, Level 16, State 1, Line 1

Conversion failed when converting the varchar value » to data type int.

we are adding backslash sign between empid and empsalary and coverting the whole into varchar but why it’s throwing error

The  Reason is empid is a int field empsalary is a float field and we are doing a complete conversion of all values to varchar that’s why it is throwing error 

In order to fix this error Cast Empid Seperately to varchar and same with Empsalary as varchar than added them to backslash.

select cast(empid as varchar)+»+ cast(empsalary as varchar) as ‘EmpidEmpsalary’ from Employee1_error1

Output

EmpidEmpsalary

15000

26000

38000

49000

510000

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Control service ошибка 1062 служба не запущена
  • Control service ошибка 1061