Sql 插入/更新时将数据类型varchar转换为数字时出错

Sql 插入/更新时将数据类型varchar转换为数字时出错,sql,sql-server,database,sql-server-2012,Sql,Sql Server,Database,Sql Server 2012,我试图使用merge语句批量插入/更新记录。但我得到以下错误。我在网上搜索过,但找不到修复的方法。有人能告诉我哪里做错了吗 插入时将数据类型varchar转换为数值时出错' 表结构 CREATE TABLE [Metric].[MetricGoal] ( [metricGoalId] [int] IDENTITY(1,1) NOT NULL, [profileConfigId] [int] NOT NULL, [metricGoalName] [varchar](20

我试图使用merge语句批量插入/更新记录。但我得到以下错误。我在网上搜索过,但找不到修复的方法。有人能告诉我哪里做错了吗

插入时将数据类型varchar转换为数值时出错'

表结构

 CREATE TABLE [Metric].[MetricGoal]
 (
    [metricGoalId] [int] IDENTITY(1,1) NOT NULL,
    [profileConfigId] [int] NOT NULL,
    [metricGoalName] [varchar](200) NULL,
    [metricIndicatorId] [int] NOT NULL,
    [marketConfigId] [int] NOT NULL,
    [regionConfigId] [int] NOT NULL,
    [goalYearConfigId] [int] NOT NULL,
    [goalPeriodConfigId] [int] NOT NULL,
    [targetValue] [decimal](20, 3) NULL,
    [actualValue] [decimal](20, 3) NULL,
    [metricGoalStatusConfigId] [int] NOT NULL,
    [metricGoalStatusReasonConfigId] [int] NOT NULL,
    [ownerId] [int] NULL,
    [workerId] [int] NULL,
    [createdOn] [datetime] NOT NULL,
    [createdBy] [int] NOT NULL,
    [updatedOn] [datetime] NOT NULL,
    [updatedBy] [int] NOT NULL,
    [lineOfBusinessConfigId] [int] NULL,
    [productConfigId] [int] NULL,
    [serviceAreaConfigId] [int] NULL,
  )
用户定义的表类型(创建的类型仅包含需要插入/更新的列):

要使用“合并”插入/更新的存储过程:

CREATE PROCEDURE [Metric].[prMaintainMetricGoalBulkLoad]
    @currUserId INT = NULL,
    @currProfileConfigId INT = NULL,
    @tblMetricGoal [Metric].[MetricGoalType3] READONLY
AS
    DECLARE @now DATETIME = GETDATE()
BEGIN
    SET NOCOUNT ON;

    MERGE INTO [Metric].[MetricGoal] T
    USING @tblMetricGoal S ON (T.metricGoalId = S.metricGoalId)

    WHEN MATCHED 
       THEN UPDATE
            SET T.targetValue = CASE WHEN S.targetValue = '' THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.targetValue,'')),T.targetValue) END, 
                T.actualValue = CASE WHEN S.actualValue = '' THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.actualValue,'')),T.actualValue) END,  
                T.metricGoalStatusConfigId = CASE WHEN S.metricGoalStatusConfigId =  -1 THEN NULL ELSE ISNULL(S.metricGoalStatusConfigId,T.metricGoalStatusConfigId) END, 
                T.metricGoalStatusReasonConfigId = CASE WHEN S.metricGoalStatusReasonConfigId = -1 THEN NULL ELSE ISNULL(S.metricGoalStatusReasonConfigId,T.metricGoalStatusReasonConfigId) END, 
                T.ownerId = CASE WHEN S.ownerId = -1 THEN NULL ELSE ISNULL(S.ownerId,T.ownerId) END, 
                T.workerId = CASE WHEN S.workerId = -1 THEN NULL ELSE ISNULL(S.workerId,T.workerId) END, 
                T.updatedOn = @now,
                T.updatedBy = @currUserId

WHEN NOT MATCHED BY TARGET
    THEN INSERT (profileConfigId,
                 --metricGoalName,
                 metricIndicatorId, lineOfBusinessConfigId, marketConfigId,
                 --productConfigId,
                 --serviceAreaConfigId,
                 --regionConfigId,
                 goalYearConfigId, goalPeriodConfigId, targetValue, actualValue,
                 metricGoalStatusConfigId, metricGoalStatusReasonConfigId,
                 ownerId, workerId, createdOn,  createdBy, 
                 updatedOn, updatedBy)
         VALUES (@currProfileConfigId,
                 --S.metricGoalName,
                 S.metricIndicatorId, S.lineOfBusinessConfigId, S.marketConfigId,
                 --NULLIF(S.productConfigId,-1),
                 --NULLIF(S.serviceAreaConfigId,-1),
                 --S.regionConfigId,
                 S.goalYearConfigId, S.goalPeriodConfigId,
                 CONVERT(DECIMAL(20,3),NULLIF(S.targetValue,'')),
                 CONVERT(DECIMAL(20,3),NULLIF(S.actualValue,'')),
                 S.metricGoalStatusConfigId, S.metricGoalStatusReasonConfigId,
                 NULLIF(S.ownerId, -1),
                 NULLIF(S.workerId, -1),
                 @now, @currUserId, @now, @currUserId);
END
执行(使用SQL Server探查器获取以下语句)


有些数据无法正确转换,确切地说是什么或在什么地方转换,但由于您表示正在使用SQL Server 2012,请使用或而不是
convert
cast

如果无法转换数据,这两个较新的函数不会导致故障,它们只返回NULL。虽然这可能无法解决坏数据,但确实有帮助。例如,您可以在where子句中使用这些

 select * 
 from to_be_imported
 where try_convert(date,stringcolumn) IS NULL

语句的insert部分似乎与表定义不一致。插入列表中的第三个字段是LineOfBusiness ConfigId,它试图插入表的第三个字段,即varchar列metricGoalName

这两行包含错误:

T.targetValue = CASE WHEN S.targetValue = '' THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.targetValue,'')),T.targetValue) END, 
T.actualValue = CASE WHEN S.actualValue = '' THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.actualValue,'')),T.actualValue) END, 
targetValue和actualValue都是十进制的(20,3),那么如何将
'
字符串
十进制一起使用呢

应该是

T.targetValue = CASE WHEN S.targetValue is null THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.targetValue,null)),T.targetValue) END, 
T.actualValue = CASE WHEN S.actualValue is null THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.actualValue,null)),T.actualValue) END, 
即使它没有意义,但至少不会从
varchar
转换为
numeric

下面是如何重现错误(我将使用变量而不是表格):


当你试图用
'
来对抗十进制时,你会得到错误,因为
'
无法转换成
十进制

使用
try\u convert
try\u cast
而不是
convert
cast
“我已经尝试过”。。。什么?您是否尝试在where子句中使用try_cast隔离问题?我希望你能意识到我所能做的就是给你提供工具,恐怕你得用这些数据做艰苦的工作你太棒了。我确实找到了错误的地方,但没有找到解决方法,现在就是。多亏了你
T.targetValue = CASE WHEN S.targetValue = '' THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.targetValue,'')),T.targetValue) END, 
T.actualValue = CASE WHEN S.actualValue = '' THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.actualValue,'')),T.actualValue) END, 
T.targetValue = CASE WHEN S.targetValue is null THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.targetValue,null)),T.targetValue) END, 
T.actualValue = CASE WHEN S.actualValue is null THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(S.actualValue,null)),T.actualValue) END, 
declare @StargetValue DECIMAL(20,3) = 10, @TtargetValue DECIMAL(20,3) = 20;
set @ttargetValue = CASE WHEN @StargetValue = '' THEN NULL ELSE ISNULL(CONVERT(DECIMAL(20,3),NULLIF(@StargetValue,'')),@TtargetValue) END