提问人:Almo 提问时间:7/27/2023 最后编辑:Almo 更新时间:7/31/2023 访问量:74
在 SQL INSERT CASE 查询中将 int 转换为日期时转换失败
Conversion failure converting int to date within an SQL INSERT CASE query
问:
我在这里阅读了许多文章(例如,在 CASE 语句中使用 CAST 时的数据转换错误),这些文章讨论了数据类型优先级是我今天一直在努力解决的问题的原因,但我认为我的是不同的。我的一台开发计算机正在运行 SQL Server,并创建了一个运行兼容级别 110 的数据库。我创建了一个表格:-
CREATE TABLE [dbo].[SyncDataRecords](
[ID] [int] IDENTITY(1,1) NOT NULL,
[SyncDataID] [int] NOT NULL,
[FldVar] [sql_variant] NULL,
CONSTRAINT [PK_SyncRecords_1] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
我还有另一个表格,其中列出了我的应用程序中涉及的字段:-
CREATE TABLE [dbo].[SyncDataFields](
[ID] [int] IDENTITY(1,1) NOT NULL,
[SyncDataID] [int] NOT NULL,
[FldName] [nvarchar](128) NOT NULL,
[FldBaseType] [nvarchar](32) NOT NULL,
[PK] [bit] NOT NULL,
CONSTRAINT [PK_SyncDataFields] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
针对此数据库,我可以通过 SqlClient.SqlCommand 参数化命令从应用程序中成功执行以下查询:-
DECLARE @FldTyp NVARCHAR(16);
SELECT @FldTyp = UPPER(FldBaseType)
FROM SyncDataFields
WHERE SyncDataID = @SyncDataID
AND PK = 1;
INSERT INTO SyncDataRecords
(SyncDataID,
FldVar)
VALUES (@SyncDataID,
CASE
WHEN @FldTyp = 'SQL_VARIANT' THEN CAST(@FldVar AS SQL_VARIANT)
WHEN @FldTyp = 'NVARCHAR' THEN CAST(@FldVar AS NVARCHAR(4000))
WHEN @FldTyp = 'BIGINT' THEN CAST(@FldVar AS BIGINT)
WHEN @FldTyp = 'BIT' THEN CAST(@FldVar AS BIT)
WHEN @FldTyp = 'DECIMAL' THEN CAST(@FldVar AS DECIMAL)
WHEN @FldTyp = 'INT' THEN CAST(@FldVar AS INT)
WHEN @FldTyp = 'MONEY' THEN CAST(@FldVar AS MONEY)
WHEN @FldTyp = 'NUMERIC' THEN CAST(@FldVar AS NUMERIC)
WHEN @FldTyp = 'SMALLINT' THEN CAST(@FldVar AS SMALLINT)
WHEN @FldTyp = 'SMALLMONEY' THEN CAST(@FldVar AS SMALLMONEY)
WHEN @FldTyp = 'TINYINT' THEN CAST(@FldVar AS TINYINT)
WHEN @FldTyp = 'FLOAT' THEN CAST(@FldVar AS FLOAT)
WHEN @FldTyp = 'REAL' THEN CAST(@FldVar AS REAL)
WHEN @FldTyp = 'DATE' THEN CAST(@FldVar AS DATE)
WHEN @FldTyp = 'DATETIME' THEN CAST(@FldVar AS DATETIME)
WHEN @FldTyp = 'SMALLDATETIME' THEN CAST(@FldVar AS SMALLDATETIME)
WHEN @FldTyp = 'TIME' THEN CAST(@FldVar AS TIME)
WHEN @FldTyp = 'CHAR' THEN CAST(@FldVar AS CHAR)
WHEN @FldTyp = 'VARCHAR' THEN CAST(@FldVar AS VARCHAR(4000))
WHEN @FldTyp = 'NCHAR' THEN CAST(@FldVar AS NCHAR)
WHEN @FldTyp = 'VARBINARY' THEN CAST(@FldVar AS VARBINARY)
ELSE CAST(@FldVar AS SQL_VARIANT)
END);
SELECT @@IDENTITY;
作为测试,我将 @SyncDataID 设置为 1(整数),将 @FldVar设置为 1234(整数),这导致@FldTyp为“INT”。然后,我创建了一个使用 Azure 托管的重复数据库和表,默认为兼容级别 150。我可以通过 SSMS 成功执行相同的查询,并根据需要声明其他变量。但是,如果我将应用程序连接到 Azure 托管的 SQL 数据库,则会引发错误
不允许从数据类型 int 到 date 的显式转换
使应用程序成功的唯一方法是将 Azure SQL 数据库的兼容级别降低到 110,以匹配我的开发级别。即使将 CASE 更改为 IF ELSE IF 也无济于事,我仍然收到完全相同的错误。
我使用的触发错误的代码是这样的:
objInsPKCommand.CommandText = "DECLARE @FldTyp nvarchar(16);SELECT @FldTyp=UPPER(FldBaseType) FROM SyncDataFields WHERE SyncDataID=@SyncDataID AND PK=1;INSERT INTO SyncDataRecords (SyncDataID, FldVar) VALUES (@SyncDataID, CASE WHEN @FldTyp='SQL_VARIANT' THEN CAST(@FldVar AS sql_variant) WHEN @FldTyp='NVARCHAR' THEN CAST(@FldVar AS NVARCHAR(4000)) WHEN @FldTyp='BIGINT' THEN CAST(@FldVar AS BigInt) WHEN @FldTyp='BIT' THEN CAST(@FldVar AS Bit) WHEN @FldTyp='DECIMAL' THEN CAST(@FldVar AS decimal) WHEN @FldTyp='INT' THEN CAST(@FldVar AS Int) WHEN @FldTyp='MONEY' THEN CAST(@FldVar AS Money) WHEN @FldTyp='NUMERIC' THEN CAST(@FldVar AS Numeric) WHEN @FldTyp='SMALLINT' THEN CAST(@FldVar AS SmallInt) WHEN @FldTyp='SMALLMONEY' THEN CAST(@FldVar AS SMALLMONEY) WHEN @FldTyp='TINYINT' THEN CAST(@FldVar AS tinyint) WHEN @FldTyp='FLOAT' THEN CAST(@FldVar AS float) WHEN @FldTyp='REAL' THEN CAST(@FldVar AS Real) WHEN @FldTyp='DATE' THEN CAST(@FldVar AS Date) WHEN @FldTyp='DATETIME' THEN CAST(@FldVar AS DateTime) WHEN @FldTyp='SMALLDATETIME' THEN CAST(@FldVar AS SmallDateTime) WHEN @FldTyp='TIME' THEN CAST(@FldVar AS Time) WHEN @FldTyp='CHAR' THEN CAST(@FldVar AS char) WHEN @FldTyp='VARCHAR' THEN CAST(@FldVar AS VarChar(4000)) WHEN @FldTyp='NCHAR' THEN CAST(@FldVar AS NChar) WHEN @FldTyp='VARBINARY' THEN CAST(@FldVar AS varbinary) ELSE CAST(@FldVar AS sql_variant) END);SELECT @@IDENTITY;"
objInsPKCommand.Parameters.Add("SyncDataID", SqlDbType.Int)
objInsPKCommand.Parameters.Add("FldVar", SqlDbType.Variant)
objInsPKCommand.Parameters.Item("SyncDataID").Value = 1
objInsPKCommand.Parameters.Item("FldVar").Value = 1234
intPKID = objInsPKCommand.ExecuteScalar
请有人能够为我指出解释何时发生更改的方向,以及我可能需要如何更改我的查询命令,以便它继续在兼容级别 150 下工作。提前非常感谢。
相关记录的 SyncDataFields 表示例:-
编号 | SyncDataID | FldName(英语:FldName) | FldBaseType | PK型 |
---|---|---|---|---|
70 | 19 | 编号 | 整数 | 1 |
71 | 19 | 名字 | NVarChar | 0 |
72 | 19 | 样式代码 | NVarChar | 0 |
73 | 19 | 批发GBP | 十进制 | 0 |
101 | 19 | 品牌 | NVarChar | 0 |
答: 暂无答案
评论
CAST(@FldVar AS NCHAR)
@FldVar
(如 )
来获取新插入的标识值。有关原因的解释,请参阅此博客文章@@IDENTITY
+SQL_VARIANT
SqlDbType.Variant
SQL_VARIANT
CASE
SyncDataFields
CASE