【问题标题】:How do I change the Data Type of a Column on TSQL? Specifically when the Data Type is VARCHAR to a INT?如何更改 TSQL 上列的数据类型?特别是当数据类型是 VARCHAR 到 INT 时?
【发布时间】:2020-09-26 19:39:45
【问题描述】:

我有一张表,它有三列,school_name、school_number、total_Enrollments。但是,total_Enrollments 被加载为 VARCHAR 列数据类型。因此,该列有额外的空格和字符。

场景:A 学校有 621 名招生,但该字段加载了一个额外的空格到 631_,下划线代表空白字段,当我尝试总结时,它不会因为它是 VARCHAR 所以我将其转换为INT 为了总结它(披露:我不是以这种方式设计此表的人,该字段从一开始就应该是数字或 INT)但它失败了。

解决方案:我无法重建此表,有没有办法通过 T-SQL 更改数据类型并删除奇怪的字符和多余的空格,以便我可以使用 SUM 函数来统计列?

【问题讨论】:

  • 数字不包含换行符。您需要干净的数据才能更改数据类型。
  • 有一个函数 try_cast docs.microsoft.com/en-us/sql/t-sql/functions/… 尝试转换一个 varchar,如果它失败不会返回错误而是返回一个空值。您当然可以修剪 docs.microsoft.com/en-us/sql/t-sql/functions/… try_cast 之前的列,以便首先删除前面或末尾的空格。
  • 您的列是应该只包含int 数据,还是也可以包含numeric 数据?例如,'1.0' 之类的值不能直接转换为 int
  • 请注意,trim 有一个可选语法来删除特定集合中的字符,例如declare @WhiteSpace as VarChar(10) = Char( 9 ) + Char( 10 ) + Char( 13 ) + Char( 32 ); ... Trim( @WhiteSpace from MyColumn ) ... 删除制表符、换行符、回车符和空格。
  • 添加一个新的可为空的 int 列。用try_cast 的结果填充它。然后,您可以选择如何处理失败的值 - 修复或删除。准备好后,删除旧列并将新旧列重命名为旧列名。注意:注意可能依赖于旧列的事情。

标签: tsql


【解决方案1】:

1) 如果您可以确保所需的数字在字符串的最左侧,并且您有多个非数字字符,则可以使用:

DROP TABLE IF EXISTS #source;
CREATE TABLE #source(total_Enrollments VARCHAR(100));
INSERT INTO #source VALUES ('101'), ('102_'), ('103 ');
INSERT INTO #source VALUES ('200' + CHAR(9)), ('201' + CHAR(10)), ('202' + CHAR(13));
INSERT INTO #source VALUES (CHAR(9) + '300'), (CHAR(10) + '301'), (CHAR(13) + '303');

SELECT
    total_Enrollments =
    CASE WHEN PATINDEX('%[^0-9]%', total_Enrollments) = 0
         THEN CAST(total_Enrollments AS INT)
         ELSE CAST(LEFT(total_Enrollments, PATINDEX('%[^0-9]%', total_Enrollments ) - 1) AS INT) END
  , pos  = PATINDEX('%[^0-9]%', total_Enrollments)
  , orig = total_Enrollments
FROM #source

PATINDEX('%[^0-9]%') 使用 RegEx 其中 %[^0-9]% 找到任何字符的第一个位置NOT(用 ^ 表示)在 0 到 9 之间的范围内。不幸的是,REPLACE-函数无法处理正则表达式来替换多个位置的非数字字符。

2) 如果您必须处理 CHAR(0),您可以通过将其替换为 REPLACE-Function 来执行此操作,下面在子选择中完成此操作。

DROP TABLE IF EXISTS #source;
CREATE TABLE #source(total_Enrollments VARCHAR(100));
INSERT INTO #source VALUES (CHAR(0) + '400' + CHAR(9));

SELECT
    total_Enrollments =
    CASE WHEN PATINDEX('%[^0-9]%', total_Enrollments) = 0
         THEN CAST(total_Enrollments AS INT)
         ELSE CAST(LEFT(total_Enrollments, PATINDEX('%[^0-9]%', total_Enrollments ) - 1) AS INT) END
  , pos  = PATINDEX('%[^0-9]%', total_Enrollments)
  , orig = total_Enrollments
FROM (SELECT total_Enrollments = REPLACE(total_Enrollments , CHAR(0), '') FROM #source) AS sub

请注意,REPLACE 仅当 CHAR(10) 出现在字符串的开头时才会查找并替换它。如果它出现在任何其他位置,您必须使用其他排序规则

SELECT total_Enrollments = REPLACE(total_Enrollments COLLATE SQL_Latin1_General_CP1_CI_AS, CHAR(0), '') 来自#source

【讨论】:

  • 我非常感谢您 1,教我一些新东西,以及 2 绝对修复我表中的那一列。这非常有效,我希望我能向您捐款,感谢您花时间帮助一个完全陌生的人,只知道您刚刚将我们从一个相当大的延误中解救了出来,我对您的感激不尽。
【解决方案2】:

您必须尝试更新表格

UPDATE <your_table>
SET total_Enrollments = REPLACE(total_Enrollments , CHAR(0), '')
WHERE CHARINDEX(CHAR(0), total_Enrollments ) > 0;

但是您还需要修复将这些不良数据放入表中的任何问题

SELECT CONVERT(INT, REPLACE(total_Enrollments , CHAR(0), ''))
FROM <your_table>;

【讨论】:

    猜你喜欢
    • 2022-08-11
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-03
    • 1970-01-01
    相关资源
    最近更新 更多