【问题标题】:LEN() & CHARINDEX() problem in formatting field格式化字段中的 LEN() 和 CHARINDEX() 问题
【发布时间】:2019-06-28 03:06:28
【问题描述】:

我有以下疑问:

UPDATE P
SET Street = TRIM(LEFT(FormattedAddress, CHARINDEX(',', FormattedAddress)-1)),
    Town = TRIM(RIGHT(FormattedAddress, LEN(FormattedAddress)-CHARINDEX(',', FormattedAddress)))
FROM Person P

它突然开始失败并出现以下错误:

消息 537,第 16 级,状态 2,第 3 行

传递给 LEFT 或 SUBSTRING 函数的长度参数无效。 声明已终止。

我怎样才能找到导致此失败的数据并修复更新语句以使其将来不会失败?

【问题讨论】:

  • 这一切都取决于如果FormattedAddress 不包含,,您希望发生什么,这是触发错误的原因。 (注意,尝试解析地址是problematic in general anyway。)

标签: sql sql-server tsql


【解决方案1】:

我怎样才能找到导致此失败的数据并修复 更新语句,使其在未来不会失败?

试试这样找。您将获得破坏查询的行。

SELECT * FROM
Person P
WHERE CHARINDEX(',', FormattedAddress) <=0 

Jeroen Mostert 建议的编写相同查询的更好方法如下。

SELECT * FROM
Person P
WHERE FormattedAddress NOT LIKE '%,%'

【讨论】:

  • 这是WHERE FormattedAddress NOT LIKE '%,%'的一种非常复杂和多余的写法。
  • 感谢您指出这一点@JeroenMostert。我已经更新了答案。
  • 感谢 PSK,有没有办法让 UPDATE 语句考虑到这一点。如果我添加 WHERE FormattedAddress NOT LIKE '%,%' 我现在得到 Msg 536, Level 16, State 2, Line 3 传递给 RIGHT 函数的无效长度参数。声明已终止。
  • NOT LIKE '%,%' 肯定会抛出错误,我编写查询以返回会破坏您的更新的行。您需要排除此类记录,因此请将 WHERE FormattedAddress LIKE '%,%'
  • 感谢@PSK,它成功了并将其添加到我的更新查询的底部,这意味着我根本不需要更改它的功能并冒险破坏它。
【解决方案2】:

您收到错误是因为 FormattedAddress 中有没有“,”的值,因此 CHARINDEX 函数会将这些值返回为 0。因为对于 LEFTRIGHTSUBSTRING 函数只接受大于 0 的正整数,这些行将引发错误。

您可以使用以下查询轻松识别导致问题的行

SELECT
    *
    FROM Person P
        WHERE CHARINDEX(',', FormattedAddress) = 0 

有多种方法可以克服相同的问题

方法#1

LEFT / RIGHT 中的用例

UPDATE P
SET
    Street = TRIM(LEFT(FormattedAddress, 
                            CASE WHEN CHARINDEX(',', FormattedAddress)>1
                                    THEN CHARINDEX(',', FormattedAddress)-1
                                ELSE LEN(FormattedAddress) END)
                                ),
    Town = TRIM(RIGHT(FormattedAddress, 
                                CASE WHEN CHARINDEX(',', FormattedAddress)>0
                                        THEN LEN(FormattedAddress)-CHARINDEX(',', FormattedAddress)
                                    ELSE LEN(FormattedAddress) END)
                                    )
    FROM Person P

方法#2

过滤WHERE子句中的记录

UPDATE P
SET
    Street = TRIM(LEFT(FormattedAddress, CHARINDEX(',', FormattedAddress)-1)),
    Town = TRIM(RIGHT(FormattedAddress, LEN(FormattedAddress)-CHARINDEX(',', FormattedAddress)))
    FROM Person P
        WHERE CHARINDEX(',', FormattedAddress) > 1

【讨论】:

  • 从 cmets 到其他答案,似乎在某些情况下 FormattedAddress 的 LEN 返回 0 - 这意味着它要么是空字符串,要么只是 whichspaces。这也应该包括在内。
  • 方法 #1 在语法上无效;检查你的括号。即使在修复它之后,如果没有,,它也会将StreetTown 设置为等于FormattedAddress。这可能是不可取的(尽管从技术上讲,OP 没有说应该发生什么)。如果FormattedAddress, 开头,那就更糟了。
  • @JeroenMostert 我已经更新并修复了 Approach# 1 的问题
【解决方案3】:

你可以使用WHERE停止:

WHERE FormattedAddress LIKE '%,%'

不过,你也可以这样做:

UPDATE P
     SET Street = TRIM(LEFT(FormattedAddress, CHARINDEX(',', FormattedAddress + ',')-1)),
     Town = TRIM(RIGHT(FormattedAddress, LEN(FormattedAddress)-CHARINDEX(',', FormattedAddress)))
FROM Person P;

【讨论】:

  • 谢谢,但现在给出以下错误:Msg 536, Level 16, State 2, Line 3 传递给 RIGHT 函数的长度参数无效。声明已终止。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-21
  • 2013-01-26
  • 2013-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多