【问题标题】:SMALLINT to VARCHAR conversion in SELECT / CASE statement in SQL querySQL 查询中 SELECT / CASE 语句中的 SMALLINT 到 VARCHAR 转换
【发布时间】:2018-12-26 20:41:37
【问题描述】:

我正在编写一个代码,该代码采用十进制输出并将其更改为缩写的十六进制输出。但是,当我尝试将 smallint 格式转换为 varchar 时,我收到一条错误消息。当我运行下面的代码时,我收到错误消息

消息 245,第 16 级,状态 1,第 1 行
将 varchar 值 'E' 转换为数据类型 smallint 时转换失败

我尝试将SELECT 语句转换为:

SELECT 
    *, 
    CONVERT(VARCHAR, PCM_ID1)

但这会返回相同的错误消息。我也将代码修改为

...
WHEN PCM_ID1 = '10' THEN CAST('A' AS VARCHAR)
WHEN PCM_ID1 = '11' THEN CAST('B' AS VARCHAR)
WHEN PCM_ID1 = '12' THEN CAST('C' AS VARCHAR)
WHEN PCM_ID1 = '13' THEN CAST('D' AS VARCHAR)
WHEN PCM_ID1 = '14' THEN CAST('E' AS VARCHAR)
WHEN PCM_ID1 = '15' THEN CAST('F' AS VARCHAR)
...

这也会返回相同的错误消息。原始代码示例如下:

SELECT 
    *, 
FROM
    dbo.DMV_All_Tests
CROSS APPLY 
    (SELECT
         CASE
            WHEN PCM_ID1 = '0' THEN '0'
            WHEN PCM_ID1 = '1' THEN '1'
            WHEN PCM_ID1 = '2' THEN '2'
            WHEN PCM_ID1 = '3' THEN '3'
            WHEN PCM_ID1 = '4' THEN '4'
            WHEN PCM_ID1 = '5' THEN '5'
            WHEN PCM_ID1 = '6' THEN '6'
            WHEN PCM_ID1 = '7' THEN '7'
            WHEN PCM_ID1 = '8' THEN '8'
            WHEN PCM_ID1 = '9' THEN '9'
            WHEN PCM_ID1 = '10' THEN 'A'
            WHEN PCM_ID1 = '11' THEN 'B' 
            WHEN PCM_ID1 = '12' THEN 'C'
            WHEN PCM_ID1 = '13' THEN 'D'
            WHEN PCM_ID1 = '14' THEN 'E'
            WHEN PCM_ID1 = '15' THEN 'F'
            WHEN PCM_ID1 = '16' THEN '10'
            ELSE PCM_ID1
         END AS [PCM ID1 Dec2Hex]) ca
WHERE
    KeyDateTime BETWEEN '2018/11/01' AND '2018/12/01' 
    AND ca.[PCM ID1 Dec2Hex] = '1'

我的目标是完成一次成功的转换,这样 PCM_ID1 不会存储在数据库中,而是存储在数据库中的 '14',它会给我等效的十六进制值,如 'F' 或 '0F'。这将用于与我们的其他数据库进行交叉检查,该数据库将这些 PCM_ID1 值存储为十六进制。

【问题讨论】:

  • 那么 PCM_ID1 是 smallint 还是 varchar?
  • PCM_ID1 原来是 (smallint, null)。
  • 如果您至少使用 SQL Server 2012,只需使用 format(PCM_ID1, N'X')
  • 发生这种情况是因为您有一个 else 子句返回列 PCM_ID1,它是 smallint。由于 smallint 比 varchar 具有更高的优先级,sql server 正在尝试将 case 子句中的其他值转换为 smallint。
  • 为什么不SELECT CONVERT(VARBINARY(8), PCM_ID1) 然后修剪呢?

标签: sql sql-server type-conversion varchar


【解决方案1】:

所以我重新创建了你的错误:

DECLARE @X TABLE (PCM_ID1 smallint)

INSERT INTO @X SELECT 14
INSERT INTO @X SELECT 1

    SELECT
    CASE
        WHEN PCM_ID1 = '0' THEN '0'
        WHEN PCM_ID1 = '1' THEN '1'
        WHEN PCM_ID1 = '2' THEN '2'
        WHEN PCM_ID1 = '3' THEN '3'
        WHEN PCM_ID1 = '4' THEN '4'
        WHEN PCM_ID1 = '5' THEN '5'
        WHEN PCM_ID1 = '6' THEN '6'
        WHEN PCM_ID1 = '7' THEN '7'
        WHEN PCM_ID1 = '8' THEN '8'
        WHEN PCM_ID1 = '9' THEN '9'
        WHEN PCM_ID1 = '10' THEN 'A'
        WHEN PCM_ID1 = '11' THEN 'B' 
        WHEN PCM_ID1 = '12' THEN 'C'
        WHEN PCM_ID1 = '13' THEN 'D'
        WHEN PCM_ID1 = '14' THEN 'E'
        WHEN PCM_ID1 = '15' THEN 'F'
        WHEN PCM_ID1 = '16' THEN '10'
        ELSE PCM_ID1
    END AS [PCM ID1 Dec2Hex]
    FROM @X

如果你这样做,你会得到同样的错误。原因是您的 case 语句中的 ELSE 返回了一个 smallint 字段,该字段使字段 [PCM ID1 Dec2Hex] smallint 并且您收到错误消息。

如果您将 else 转换为 varchar,它将解决此问题。问题是它试图将 E 转换回 smallint。我希望这是有道理的。

DECLARE @X TABLE (PCM_ID1 smallint)

INSERT INTO @X SELECT 14
INSERT INTO @X SELECT 1

    SELECT
    CASE
        WHEN PCM_ID1 = '0' THEN '0'
        WHEN PCM_ID1 = '1' THEN '1'
        WHEN PCM_ID1 = '2' THEN '2'
        WHEN PCM_ID1 = '3' THEN '3'
        WHEN PCM_ID1 = '4' THEN '4'
        WHEN PCM_ID1 = '5' THEN '5'
        WHEN PCM_ID1 = '6' THEN '6'
        WHEN PCM_ID1 = '7' THEN '7'
        WHEN PCM_ID1 = '8' THEN '8'
        WHEN PCM_ID1 = '9' THEN '9'
        WHEN PCM_ID1 = '10' THEN 'A'
        WHEN PCM_ID1 = '11' THEN 'B' 
        WHEN PCM_ID1 = '12' THEN 'C'
        WHEN PCM_ID1 = '13' THEN 'D'
        WHEN PCM_ID1 = '14' THEN 'E'
        WHEN PCM_ID1 = '15' THEN 'F'
        WHEN PCM_ID1 = '16' THEN '10'
        ELSE CAST(PCM_ID1 AS VARCHAR)
    END AS [PCM ID1 Dec2Hex]
    FROM @X

【讨论】:

    【解决方案2】:
    declare @input as smallint = 1;
    select format(@input, 'X');
    

    【讨论】:

      猜你喜欢
      • 2011-11-01
      • 2014-12-05
      • 2015-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多