在我的代码中没有int参数的情况下将varchar转换为int的sql错误

时间:2019-03-16 14:36:55

标签: sql-server tsql stored-procedures

我正在尝试编写一个sp,用于将数据插入到我的表中。在我的sp中,我有一个字段跟踪,没有我实现的大多数代码都与此相关。但我遇到此错误:

  

将varchar值'SRFCHE-600-R-1000000'转换为数据类型int时转换失败。   tracingno的类型是varchar,但我无法理解为什么会遇到此错误。

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[spInsertRecieptTracing_tblRecieptTracing]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure [dbo].[spInsertRecieptTracing_tblRecieptTracing]
GO

create procedure spInsertRecieptTracing_tblRecieptTracing (
    @RecieptTracingID UniqueIdentifier,
    @RecieptItemRef UniqueIdentifier,
    @TracingNo varchar(4000),
    @ExecuteID UniqueIdentifier, 
    @Quantity Decimal(25,5),
    @ExpireDateStr varchar(4000),
    @ExpireDate datetime,
    @ManufacturingDateStr varchar(4000),
    @LotNo varchar(4000),
    @IsBarCode Bit,
    @ManufacturingDate DateTime,
    @PartOptionName varchar(1000) = null,
    @partcode varchar (100)
)
with Encryption
as 

declare @_tracingno varchar (1000)
if  exists ( 
    select * 
    from ims.tblsettings where IsPartInTracingno = 1
)
begin
    if exists (
        select top 1 TracingNo 
        from ims.tblRecieptTracing 
        where TracingNo like '%-%')
    begin

    set @_tracingno = (
        select max( right(TracingNo, charindex('-', reverse(TracingNo) + '-') - 1)) 
        from ims.tblRecieptTracing
    )

    end
    else
    begin
        set @_tracingno = 1000000
    end
end
else
begin 
    set @_tracingno=''
end

if(@IsBarCode is null)
    set @IsBarCode =0;

if(@IsBarCode =0)
    begin
        SET @TracingNo = NULL;
    end


IF(EXISTS(
    SELECT * 
    FROM IMS.tblRecieptTracing 
    WHERE RecieptItemRef = @RecieptItemRef 
 ) and @IsBarCode = 0)
    update IMS.tblRecieptTracing 
    set ExecuteID=@ExecuteID, 
        Quantity = @Quantity, 
        ExpireDateStr = @ExpireDateStr, 
        ExpireDate = @ExpireDate, 
        PartOptionName = @PartOptionName
    Where RecieptItemRef = @RecieptItemRef

ELSE 
    BEGIN
    if(@TracingNo is null)
    begin
        if exists(select * from ims.tblsettings where IsPartInTracingno=1)
        begin
            SELECT @TracingNo = @partcode + '-' + cast(@_tracingno as varchar) 
            FROM IMS.tblRecieptTracing ;
            IF(@TracingNo IS NULL ) 
            begin
                SET @TracingNo = 1000000;
                SET @TracingNo = @TracingNo +1 ;
            end
            SET @TracingNo=cast (@TracingNo as varchar)
        end
        else
                --select 
            SELECT @TracingNo = cast (max( right(TracingNo, charindex('-', reverse(TracingNo) + '-') - 1))as varchar) 
            from ims.tblRecieptTracing;
            IF(@TracingNo IS NULL ) 
                SET @TracingNo = 1000000;

            SET @TracingNo = @TracingNo + 1 ;
        end

            insert into IMS.tblRecieptTracing ( 
                RecieptTracingID , 
                RecieptItemRef , 
                TracingNo  ,  
                ExecuteID ,  
                Quantity ,
                ExpireDateStr ,
                ExpireDate,
                ManufacturingDateStr,
                LotNo,
                ManufacturingDate,
                PartOptionName)
            values( 
                @RecieptTracingID, 
                @RecieptItemRef, 
                @TracingNo , 
                @ExecuteID , 
                @Quantity ,
                @ExpireDateStr ,
                @ExpireDate,
                @ManufacturingDateStr,
                @LotNo,
                @ManufacturingDate,
                @PartOptionName);
        END

我认为主要部分在这里:

SELECT @TracingNo=cast (max( right(TracingNo, charindex('-', reverse(TracingNo) + '-') - 1))as varchar) from ims.tblRecieptTracing;

2 个答案:

答案 0 :(得分:2)

100中有99次,此错误是由于SQL Server尝试将字符表达式隐式转换为int而引起的。

TL; DR;
您正在代码中的某个位置尝试比较,组合或使用字符值'SRFCHE-600-R-1000000'填充int值。

摘自Data type conversion (Database Engine)文档:

  

在以下情况下可以转换数据类型:

     
      
  • 当将一个对象的数据移动到另一个对象的数据或与之比较时,可能必须将数据从一个对象的数据类型转换为另一个对象的数据类型。
  •   
  • 将Transact-SQL结果列,返回代码或输出参数中的数据移到程序变量中时,必须将数据从SQL Server系统数据类型转换为变量的数据类型。
  •   

然后在同一页面上继续:

  

数据类型可以隐式或显式转换。

     

隐式转换对用户不可见。 SQL Server自动将数据从一种数据类型转换为另一种数据类型。例如,当将smallintint进行比较时,在进行比较之前,smallint被隐式转换为int

Data type precedence (Transact-SQL)中记录了将哪种类型的数据隐式转换为其他类型的数据:

  

SQL Server对数据类型使用以下优先顺序:

     

1种用户定义的数据类型(最高)
   2 sql_variant
   3个xml
   4 datetimeoffset
   5 datetime2
   6 datetime
   7 smalldatetime
   8日
   9次
  10浮点数
  11真实
  12位小数
  13钱
  14小钱
  15 bigint
  16 int
  17 smallint
  18 tinyint
  19位
  20个ntext
  21个文字
  22图片
  23时间戳
  24个Uniqueidentifier
  25个nvarchar(包括nvarchar(max))
  26个nchar
  27个varchar(包括varchar(max))
  28个字符
  29个varbinary(包括varbinary(max))
  30个二进制文件(最低)

答案 1 :(得分:0)

错误是由于以下原因引起的:

SET @TracingNo = @TracingNo + 1 ;

您应该将其更改为

SET @TracingNo = @TracingNo + '1' ;

请查看Zohar Peled的出色答案:nvarchar的优先级(25)比int(16)低。

因此,当您进行计算

@TracingNo + 1

引擎将使用@TracingNo和整数1的nvarchar值。为了将它们相加,它将尝试将优先级较低的数据类型项转换为较高的优先级。因此,它将尝试将@TracingNo转换为int。这正是错误消息的含义:@TracingNo值之一无法转换为int。