首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在SQL Server中修剪前导零的更好方法?

在SQL Server中修剪前导零的更好方法?
EN

Stack Overflow用户
提问于 2009-03-19 14:16:23
回答 17查看 338K关注 0票数 183

我使用this已经有一段时间了:

代码语言:javascript
复制
SUBSTRING(str_col, PATINDEX('%[^0]%', str_col), LEN(str_col))

然而,最近我发现了一个问题,所有"0“字符的列,比如”00000000“,因为它永远找不到匹配的非”0“字符。

我见过的另一种技术是使用TRIM

代码语言:javascript
复制
REPLACE(LTRIM(REPLACE(str_col, '0', ' ')), ' ', '0')

如果有嵌入的空格,这就会有问题,因为当空格变成“0”时,它们就会变成“0”。

我正在尝试避免标量UDF。我在SQL Server2005中发现了许多UDF的性能问题。

EN

回答 17

Stack Overflow用户

回答已采纳

发布于 2009-03-19 14:32:58

代码语言:javascript
复制
SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col))
票数 339
EN

Stack Overflow用户

发布于 2009-03-19 14:21:05

为什么不直接将值转换为INTEGER,然后再返回给VARCHAR

代码语言:javascript
复制
SELECT  CAST(CAST('000000000' AS INTEGER) AS VARCHAR)

--------
       0
票数 53
EN

Stack Overflow用户

发布于 2014-02-16 07:25:19

如果你有全零(甚至是一个零),这里的其他答案就不会被考虑在内。

有些总是将空字符串默认为零,这是错误的,因为它应该保留为空。

重读原来的问题。这就回答了提问者想要的。

解决方案#1:

代码语言:javascript
复制
--This example uses both Leading and Trailing zero's.
--Avoid losing those Trailing zero's and converting embedded spaces into more zeros.
--I added a non-whitespace character ("_") to retain trailing zero's after calling Replace().
--Simply remove the RTrim() function call if you want to preserve trailing spaces.
--If you treat zero's and empty-strings as the same thing for your application,
--  then you may skip the Case-Statement entirely and just use CN.CleanNumber .
DECLARE @WackadooNumber VarChar(50) = ' 0 0123ABC D0 '--'000'--
SELECT WN.WackadooNumber, CN.CleanNumber,
       (CASE WHEN WN.WackadooNumber LIKE '%0%' AND CN.CleanNumber = '' THEN '0' ELSE CN.CleanNumber END)[AllowZero]
 FROM (SELECT @WackadooNumber[WackadooNumber]) AS WN
 OUTER APPLY (SELECT RTRIM(RIGHT(WN.WackadooNumber, LEN(LTRIM(REPLACE(WN.WackadooNumber + '_', '0', ' '))) - 1))[CleanNumber]) AS CN
--Result: "123ABC D0"

解决方案#2 (包含示例数据):

代码语言:javascript
复制
SELECT O.Type, O.Value, Parsed.Value[WrongValue],
       (CASE WHEN CHARINDEX('0', T.Value)  > 0--If there's at least one zero.
              AND LEN(Parsed.Value) = 0--And the trimmed length is zero.
             THEN '0' ELSE Parsed.Value END)[FinalValue],
       (CASE WHEN CHARINDEX('0', T.Value)  > 0--If there's at least one zero.
              AND LEN(Parsed.TrimmedValue) = 0--And the trimmed length is zero.
             THEN '0' ELSE LTRIM(RTRIM(Parsed.TrimmedValue)) END)[FinalTrimmedValue]
  FROM 
  (
    VALUES ('Null', NULL), ('EmptyString', ''),
           ('Zero', '0'), ('Zero', '0000'), ('Zero', '000.000'),
           ('Spaces', '    0   A B C '), ('Number', '000123'),
           ('AlphaNum', '000ABC123'), ('NoZero', 'NoZerosHere')
  ) AS O(Type, Value)--O is for Original.
  CROSS APPLY
  ( --This Step is Optional.  Use if you also want to remove leading spaces.
    SELECT LTRIM(RTRIM(O.Value))[Value]
  ) AS T--T is for Trimmed.
  CROSS APPLY
  ( --From @CadeRoux's Post.
    SELECT SUBSTRING(O.Value, PATINDEX('%[^0]%', O.Value + '.'), LEN(O.Value))[Value],
           SUBSTRING(T.Value, PATINDEX('%[^0]%', T.Value + '.'), LEN(T.Value))[TrimmedValue]
  ) AS Parsed

结果:

摘要:

您可以使用上面的代码一次性删除前导零。

如果你打算经常重用它,那么把它放在一个内联表值函数(ITVF)中。

您对UDF的性能问题的担忧是可以理解的。

然而,这个问题只适用于全标量函数和多语句表函数。

使用ITVF是非常好的。

我们的第三方数据库也有同样的问题。

有了字母-数字字段,许多都是在没有前导空格的情况下输入的,该死的人类!

这使得在不清除丢失的前导零的情况下连接是不可能的。

结论:

与删除前导零不同,您可能需要考虑在进行连接时只用前导零填充修剪后的值。

更好的做法是,通过添加前导零来清理表中的数据,然后重新构建索引。

我认为这会更快,更简单。

代码语言:javascript
复制
SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF(' 0A10  ', ''))), 10)--0000000A10
SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF('', ''))), 10)--NULL --When Blank.
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/662383

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档