RIGHT 函数中的 Charindex 错误长度无效

Charindex error invalid length in RIGHT function

提问人:AlexisPa 提问时间:7/26/2023 最后编辑:AlexisPa 更新时间:7/26/2023 访问量:61

问:

我有一个类似于这样的SQL Server视图:

SELECT
    BATCHID, BATCHNO,  OPENDATE, 
    RIGHT(LEFT(BATCHNO, LEN(BATCHNO) - LEN(RIGHT(BATCHNO, CHARINDEX('-', REVERSE(BATCHNO)) - 1)) - 1), CHARINDEX('-', REVERSE(LEFT(BATCHNO, LEN(BATCHNO) - LEN(RIGHT(BATCHNO, CHARINDEX('-', REVERSE(BATCHNO)) - 1)) - 1))) - 1)
    AS PRODUCTNAME
FROM TABLE_A

这将产生如下结果:

批处理 巴奇诺 开放日期 产品名称
1 X-ASDF-054型 2023/01/02 ASDF公司
2 X-ASDF-033型 2023/01/05 ASDF公司
3 X-QWER-056型 2023/01/12 QWER系列

等等。

当我像这样查询表时

SELECT PRODUCTNAME, MIN(OPENDATE) AS MIN_OPENDATE 
FROM VIEW_X
GROUP BY PRODUCTNAME

一切都按预期进行。但是,当查询嵌套与此类似时(由于我所处的受监管环境,我无法避免或影响):

SELECT PRODUCTNAME
FROM (
    SELECT PRODUCTNAME, MIN(OPENDATE) AS MIN_OPENDATE
    FROM VIEW_X
    GROUP BY PRODUCTNAME
) AS sub_query
WHERE PRODUCTNAME = 'ASDF'

我收到错误

传递给 RIGHT 函数的长度参数无效。

我不知道为什么,也不知道如何解决它。我可以影响如何创建视图和子查询,但无法影响函数的嵌套。我正在寻找一种解决方案,该解决方案为我提供了使用 PRODUCTNAME 列指定产品名称的所有条目。提前非常感谢!

sql-server 子查询 charindex

评论

2赞 siggemannen 7/26/2023
你可能有一些没有“-”的 batchno,这会破坏其余的函数调用。当 charindex('-', batchno) > 0 时,您可以使用案例 ...还。。。改为结束
1赞 Thom A 7/26/2023
或者当它为 : 时的值。NULL0NULLIF(CHARINDEX('-', REVERSE(BATCHNO)),0)
1赞 siggemannen 7/26/2023
charindex 不是这样。它返回第一个“-”的位置。如果要检查两个 - - ,则应执行以下操作: case when patindex('%[-]%[-]%', batchno) > 0
2赞 Stuck at 1337 7/26/2023
顺便说一句,你有 - 为什么?DISTINCTGROUP BY
1赞 Stuck at 1337 7/27/2023
没有子查询的查询不能很好地工作:相同的错误消息。也许这个故事比你告诉我们的要多,你可以为我们构建一个更准确的 MCVE - 我怀疑你的视图有一个 where 子句或其他附加逻辑,让简单查询首先过滤掉坏行,但过滤器稍后在更复杂的查询中应用,所以在过滤掉这些行之前会尝试对它们进行表达式。

答:

1赞 Stuck at 1337 7/26/2023 #1

问题在于,你用来解析字符串部分的丑陋的大表达式可能会针对该表达式将失败的行运行(例如,没有字符的行)。BATCHNO-

相反,请执行以下操作:

SELECT
BATCHID, BATCHNO,  OPENDATE, 
CASE WHEN BATCHNO LIKE N'%[-]%[-]%' THEN
RIGHT(LEFT(BATCHNO, LEN(BATCHNO) - LEN(RIGHT(BATCHNO, 
  CHARINDEX('-', REVERSE(BATCHNO)) - 1)) - 1), 
  CHARINDEX('-', REVERSE(LEFT(BATCHNO, 
  LEN(BATCHNO) - LEN(RIGHT(BATCHNO, CHARINDEX('-', 
  REVERSE(BATCHNO)) - 1)) - 1))) - 1) 
AS PRODUCTNAME
FROM dbo.TABLE_A;

当然,SQL Server 2016+ 中一个更简单的方法是(从这个伟大的答案中提炼出来):

SELECT BATCHID, BATCHNO,  OPENDATE, 
  JSON_VALUE('["' + REPLACE(BATCHNO,'-','","') + '"]','$[1]')
  AS PRODUCTNAME
FROM dbo.TABLE_A;

db<>fiddle 中的示例。