【发布时间】: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