sql-server 我无法将char值转换为money,char值的语法不正确

xoshrz7s  于 2022-10-31  发布在  其他
关注(0)|答案(1)|浏览(1088)

我下载了一个与股票市场相关的数据库,其中的值以varchar(50)数据类型表示,我想将它们转换为货币,以便可以对它们执行操作。
遗憾的是,我无法通过以下命令或设计选项执行此操作。

ALTER TABLE dbo.NASDAQ100
ALTER COLUMN High money;

我能怎么办呢?
Cannot convert a char value to money. The char value has incorrect syntax.

ou6hu8tu

ou6hu8tu1#

在这里,您所能做的就是确定哪些值不会转换为MONEY数据类型,然后进行任何需要进行的调整来修复它们。
例如,我将创建一个包含一些虚拟数据的表,并将[low]和[high]列的数据类型设置为VARCHAR(50):

CREATE TABLE dbo.NASDAQ100
(
    [stock_code] CHAR(3)     NULL
    , [low]      VARCHAR(50) NULL
    , [high]     VARCHAR(50) NULL
) ;
GO
INSERT
    INTO    dbo.NASDAQ100 ( [stock_code], [low], [high] )
    VALUES  (   'ABB'  , '101.3348'   , '103.2577' )
            , ( 'FRG'  , '4.5098'     , '4.5663' )
            , ( 'PLA'  , '40.0001'    , '4O.2121' )
            , ( 'RDG'  , 'USD8.7890'  , 'USD11.2345' )
            , ( 'ZZT'  , '2.8q87'     , '5.6996' ) ;
GO

简单的SELECT * FROM dbo.NASDAQ100查询会传回下列结果:

stock_code | low       | high
------------------------------------
ABB        | 101.3348  | 103.2577
FRG        | 4.5098    | 4.5663
PLA        | 40.0001   | 4O.2121
RDG        | USD8.7890 | USD11.2345
ZZT        | 2.8q87    | 5.6996

如你所见,数据很脏。
如果我现在尝试将[low]和[high]列的数据类型更改为MONEY:

ALTER TABLE dbo.NASDAQ100 ALTER COLUMN [low] MONEY ;
ALTER TABLE dbo.NASDAQ100 ALTER COLUMN [high] MONEY ;

我得到一个Cannot convert a char value to money. The char value has incorrect syntax错误。
如前所述,解决此问题的唯一真实的方法是确定哪些值需要更正,然后自己手动更正它们。
下面的查询--它使用TRY_CAST内置函数--应该识别出哪些值不会成功地转换为MONEY数据类型:

WITH cte_Nasdaq100 AS
(
    SELECT      [stock_code]
                , [low] AS [low_original_value]
                , TRY_CAST ( [low] AS MONEY ) AS [low_as_money]
                , [high] AS [high_original_value]
                , TRY_CAST ( [high] AS MONEY ) AS [high_as_money]
    FROM        dbo.NASDAQ100
)
SELECT      [stock_code]
            , CASE
                WHEN    [low_as_money] IS NULL
                    THEN    [low_original_value]
                ELSE        '-'
                END AS [low_values_to_be_fixed]
            , CASE
                WHEN    [high_as_money] IS NULL
                    THEN    [high_original_value]
                ELSE        '-'
                END AS [high_values_to_be_fixed]
FROM        cte_Nasdaq100
WHERE       [high_as_money] IS NULL
    OR      [low_as_money] IS NULL ;
GO

对示例数据运行此查询,得到以下结果:

stock_code | low_values_to_be_fixed | high_values_to_be_fixed
-------------------------------------------------------------
PLA        | -                      | 4O.2121
RDG        | USD8.7890              | USD11.2345
ZZT        | 2.8q87                 | -

现在,虽然脏值已经被识别出来,但是没有办法确定它们应该是什么,这就是你需要做一些跑腿的工作并查找它们的地方。
获得正确的值后,运行一些UPDATE语句进行更正:

UPDATE      dbo.NASDAQ100
    SET     [high] = '40.2121'
    WHERE   [stock_code] = 'PLA' ;

UPDATE      dbo.NASDAQ100
    SET     [low] = '8.7890'
            , [high] = '11.2345'
    WHERE   [stock_code] = 'RDG' ;

UPDATE      dbo.NASDAQ100
    SET     [low] = '2.8987'
    WHERE   [stock_code] = 'ZZT' ;
GO

现在,一个简单的SELECT * FROM dbo.NASDAQ100查询将返回干净的数据:

stock_code | low      | high
--------------------------------
ABB        | 101.3348 | 103.2577
FRG        | 4.5098   | 4.5663
PLA        | 40.0001  | 40.2121
RDG        | 8.7890   | 11.2345
ZZT        | 2.8987   | 5.6996

如果我再次运行查询来识别脏数据(即WITH cte_Nasdaq100 AS...),它将不会返回任何结果。
现在,我可以将[low]和[high]列的数据类型更改为MONEY,而SQL Server不会显示伪数据:

ALTER TABLE dbo.NASDAQ100 ALTER COLUMN [low] MONEY ;
ALTER TABLE dbo.NASDAQ100 ALTER COLUMN [high] MONEY ;

为了进行测试,我运行了一个查询,结果中包含一个计算:

SELECT      [stock_code]
            , [low]
            , [high]
            , [high] - [low] AS [difference]
FROM        dbo.NASDAQ100 ;
GO

结果如下:

stock_code | low      | high     | difference
---------------------------------------------
ABB        | 101.3348 | 103.2577 | 1.9229
FRG        | 4.5098   | 4.5663   | 0.0565
PLA        | 40.0001  | 40.2121  | 0.212
RDG        | 8.7890   | 11.2345  | 2.4455
ZZT        | 2.8987   | 5.6996   | 2.8009

希望这对你有帮助。

相关问题