【问题标题】:How to solve error Conversion failed when converting the nvarchar value to data type integer?将nvarchar值转换为数据类型整数时如何解决错误转换失败?
【发布时间】:2022-01-08 08:55:53
【问题描述】:

我使用动态查询在 SQL Server 2014 上工作;运行查询时出现此错误:

将 nvarchar 值“24VAC/DC”转换为数据类型 int 时转换失败。

执行此动态 SQL 时出现错误

EXEC (@SQL)

请问这个错误怎么解决?

数据样本

IF OBJECT_ID('dbo.TAllfeatures') IS NOT NULL
    DROP TABLE dbo.TAllfeatures

IF OBJECT_ID('dbo.TCondition') IS NOT NULL
    DROP TABLE dbo.TCondition

IF OBJECT_ID('dbo.TPartAttributes') IS NOT NULL
    DROP TABLE dbo.TPartAttributes

IF OBJECT_ID('dbo.TAllData') IS NOT NULL
    DROP TABLE dbo.TAllData
    
CREATE TABLE [dbo].[TAllfeatures]
(
     [ZPLID] [int] NULL,
     [ZfeatureKey] [bigint] NULL,
     [FeatType] [int] NULL,
     [AcceptedValueID] [int] NULL,
     [IsNumericValues] [int] NULL
) ON [PRIMARY]
GO

INSERT INTO [dbo].[TAllfeatures] ([ZPLID], [ZfeatureKey], [FeatType], [AcceptedValueID], [IsNumericValues]) 
VALUES (75533, NULL, 0, 0, 0)
INSERT INTO [dbo].[TAllfeatures] ([ZPLID], [ZfeatureKey], [FeatType], [AcceptedValueID], [IsNumericValues]) 
VALUES (75533, 1505730001, 2044, 155, 0)
INSERT INTO [dbo].[TAllfeatures] ([ZPLID], [ZfeatureKey], [FeatType], [AcceptedValueID], [IsNumericValues]) 
VALUES (75533, 1505730011, 2044, 274, 1)

INSERT INTO [dbo].[TAllfeatures] ([ZPLID], [ZfeatureKey], [FeatType], [AcceptedValueID], [IsNumericValues]) 
VALUES (75533, 1505730036, 2044, 271, 0)
    
CREATE TABLE [dbo].[TCondition]
(
     [TradeCodeControlID] [int]  NOT NULL,
     [VersionYear] [int] NULL,
     [Version] [float] NULL,
     [CodeTypeID] [int] NULL,
     [RevisionID] [bigint] NULL,
     [Code] [varchar](20) NULL,
     [ZPLID] [int] NULL,
     [ZfeatureKey] [bigint] NULL,
     [ZfeatureType] [nvarchar](200) NULL,
     [EStrat] [nvarchar](2500) NULL,
     [EEnd] [nvarchar](2500) NULL
) ON [PRIMARY]
    
INSERT INTO [dbo].[TCondition] ([TradeCodeControlID], [VersionYear], [Version], [CodeTypeID], [RevisionID], [Code], [ZPLID], [ZfeatureKey], [ZfeatureType], [EStrat], [EEnd]) 
VALUES (8123, 2020, 26, 849774, 307683692, N'8535400000', 75533, 1505730001, NULL, N'In(''Surge Protector'',''Surge Protector for Media Lines Only'',''Outlet Strip, Surge Protector'',''PDU, Surge Protector'',''Surge Lightning Arrester'',''Surge Arrester'',''Surge Protection Module'',''Lightning Arrester'',''Lightning Current Arrester'',''Protection Device'',''Surge Voltage Equipment'',''Isolated'',''Surge Protection'',''Coaxial'',''Base Element'')', N'')

INSERT INTO [dbo].[TCondition] ([TradeCodeControlID], [VersionYear], [Version], [CodeTypeID], [RevisionID], [Code], [ZPLID], [ZfeatureKey], [ZfeatureType], [EStrat], [EEnd]) 
VALUES (8124, 2020, 26, 849774, 307683692, N'8535400000', 75533, 1505730036, NULL, N'>1000', N'')
    
CREATE TABLE [dbo].[TPartAttributes]
(
     [PartID] [int] NOT NULL,
     [ZfeatureKey] [bigint] NULL,
     [AcceptedValuesOption_Value] [float] NULL,
     [Name] [nvarchar](500) NOT NULL
) ON [PRIMARY]
GO

INSERT INTO [dbo].[TPartAttributes] ([PartID], [ZfeatureKey], [AcceptedValuesOption_Value], [Name]) 
VALUES (1128078, 1505730036, 24, N'24VAC/DC')

INSERT INTO [dbo].[TPartAttributes] ([PartID], [ZfeatureKey], [AcceptedValuesOption_Value], [Name]) 
VALUES (1128078, 1505730001, NULL, N'Surge Voltage Equipment')

INSERT INTO [dbo].[TPartAttributes] ([PartID], [ZfeatureKey], [AcceptedValuesOption_Value], [Name]) 
VALUES (1128089, 1505730036, 5, N'5V')

INSERT INTO [dbo].[TPartAttributes] ([PartID], [ZfeatureKey], [AcceptedValuesOption_Value], [Name]) 
VALUES (1128089, 1505730001, NULL, N'Attachment Plug')

INSERT INTO [dbo].[TPartAttributes] ([PartID], [ZfeatureKey], [AcceptedValuesOption_Value], [Name]) 
VALUES (27912821, 1505730001, NULL, N'Surge Protection Module')

INSERT INTO [dbo].[TPartAttributes] ([PartID], [ZfeatureKey], [AcceptedValuesOption_Value], [Name]) 
VALUES (27912821, 1505730036, 480, N'480V')

INSERT INTO [dbo].[TPartAttributes] ([PartID], [ZfeatureKey], [AcceptedValuesOption_Value], [Name]) 
VALUES (32817870, 1505730001, NULL, N'Surge Protector')

INSERT INTO [dbo].[TPartAttributes] ([PartID], [ZfeatureKey], [AcceptedValuesOption_Value], [Name]) 
VALUES (32817870, 1505730036, NULL, N'120V, 240V')
    
CREATE TABLE dbo.TAllData
(
         PartID INT,    
         Code VARCHAR(20),    
         CodeTypeID INT,    
         RevisionID BIGINT,    
         ZPLID INT,    
         ConCount INT
)

SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
            
DECLARE @ConStr nvarchar(max) = STUFF((SELECT CONCAT(' Or (PM.ZfeatureKey= ', CC.ZfeatureKey , IIF(CC.ZfeatureType='Qualifications',' And AcceptedValuesOption_Value ' , ' And Name ' ) , CAST(EStrat AS NVARCHAR(2500)),')')   --ValueName
                 FROM dbo.TCondition CC  INNER JOIN dbo.TAllfeatures AL with(nolock) ON AL.ZfeatureKey = CC.ZfeatureKey AND AL.IsNumericValues =0
                 FOR XML PATH(''), TYPE).value('(./text())[1]','varchar(max)'),1,3,'')
                
    
                    
                    
    
                    
                 DECLARE @Sql nvarchar(max)= CONCAT('INSERT INTO dbo.TAllData(PartID,Code,CodeTypeID,RevisionID,ZPLID ,ConCount)',' SELECT  PartID,Code,Co.CodeTypeID,Co.RevisionID,Co.ZPLID,Count(1) as ConCount
                    
                 FROM 
                 dbo.TPartAttributes PM with(nolock) 
                 INNER JOIN    dbo.TCondition Co with(nolock) ON Co.ZfeatureKey = PM.ZfeatureKey ',                
                 'Where (1=1 and  ' ,  @ConStr,' ) Group By PartID,Code,Co.CodeTypeID,Co.RevisionID,Co.ZPLID ' ,
                 ' Having Count(1)>= ',(SELECT COUNT(1) FROM TCondition with(nolock)))
    
            
            --print @SQL
             EXEC (@SQL)

我尝试解决问题,但问题仍然存在

DECLARE @ConStr nvarchar(max)=  STUFF((SELECT CONCAT(' Or (PM.ZfeatureKey= ''', CC.ZfeatureKey , '''', IIF(CC.ZfeatureType='Qualifications',' And AcceptedValuesOption_Value ' , ' And Name ' ) , LEFT(EStrat, 1), '''', SUBSTRING(EStrat, 2, LEN(EStrat) -1), ''')')   --ValueName
                       FROM dbo.TCondition  CC INNER JOIN dbo.TAllfeatures AL ON AL.ZfeatureKey = CC.ZfeatureKey AND AL.IsNumericValues =0
                       FOR XML PATH(''), TYPE).value('(./text())[1]','varchar(max)'),1,3,'')

【问题讨论】:

  • 老实说,这就是为什么我大力提倡使您生成的动态 SQL 也具有良好的格式... 600 多个字符长的单行 SQL 不容易阅读。
  • 一般也建议不要使用EXEC (@SQL);等语法。此类语句无法参数化,这会助长导致 SQL 注入等安全漏洞的不良习惯。如果您需要运行变量或文字字符串中的语句,请使用sys.sp_executesql。然后,如果需要,您可以轻松地对语句进行参数化。
  • 调试动态SQL最简单的方法是先PRINT/SELECT语句。然后,您可以先调试该 SQL,并在将解决方案传播到生成动态语句的 SQL 之前解决问题。通常您会发现问题非常简单,例如难以在文字字符串中停止的印刷错误、缺少空格/换行符或前导/尾随分隔符。花时间让非动态语句首先工作非常重要,好像这不起作用,动态语句将没有机会正常工作。
  • 最后,您为什么在此处的所有查询中都发送NOLOCK 提示?你为什么要使用这样的提示? NOLOCK 不是“魔术更快的按钮”,它是一个不关心错误数据的按钮。我建议阅读Bad habits : Putting NOLOCK everywhere
  • 其实我什至不确定为什么上面的语句是动态的;看来您正在使用动态语句为IN 注入Name 的值,但您可以只使用EXISTS。我越看这个,越觉得这是XY Problem

标签: sql sql-server stored-procedures sql-server-2014 dynamic-sql


【解决方案1】:

看来这里根本不需要动态 SQL。

由于缺少示例数据和预期输出,很难知道您要实现什么逻辑,而您现有的查询可以使用更好的格式。但它看起来像是某种关系划分。

请注意,除非您真的知道自己在做什么,否则不应使用WITH (NOLOCK)。它可能会给出非常不正确的结果。

我也强烈建议您在每一列上使用表引用,尤其是在子查询中

INSERT INTO dbo.TAllData
    (PartID, Code, CodeTypeID, RevisionID, ZPLID, ConCount)
SELECT
  PartID,
  Code,
  Co.CodeTypeID,
  Co.RevisionID,
  Co.ZPLID,
  Count(1) as ConCount
FROM dbo.TPartAttributes PM
INNER JOIN dbo.TCondition Co ON Co.ZfeatureKey = PM.ZfeatureKey
Where EXISTS (SELECT 1
    FROM dbo.TAllfeatures AL
    WHERE AL.ZfeatureKey = Co.ZfeatureKey
      AND AL.IsNumericValues = 0
      AND IIF(Co.ZfeatureType = 'Qualifications', AcceptedValuesOption_Value, Name) = EStrat
)
Group By
  PartID,
  Code,
  Co.CodeTypeID,
  Co.RevisionID,
  Co.ZPLID
Having Count(1) >= (SELECT COUNT(1) FROM TCondition);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-17
    • 2011-08-29
    • 2015-06-20
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多