没有前 n 个字符的子串

Van*_*nel 5 sql-server t-sql substring sql-server-2016

我正在开发一个 SQL Server 2016 存储过程,我想获取varchar(38)列的最后一个字符。

我知道总会有至少 18 个字符,我不知道列的确切长度,因为它是可变的。

我想我可以得到列的长度并做一个减法来使用SUBSTRING,但我不能这样做,因为我正在这样做:

set @externalCodes = (
    select Serial, AggregationLevel
      from ExternalCode where ProductionOrderId = @productionOrderId
    for json path
Run Code Online (Sandbox Code Playgroud)

我正在生成一个 JSON,但我不知道如何获取Serial选择中每列的长度。

我的问题是:如何在不知道长度的情况下从没有前 18 个字符的字符串中获取子字符串?

一种解决方案可能是:

SUBSTRING(Serial, 18, 38)
Run Code Online (Sandbox Code Playgroud)

并且它总是返回从 18 到字符串末尾的子字符串,即使字符串的长度不是 38。

And*_*y M 9

您的SUBSTRING解决方案似乎已经足够好了,我不确定为什么您还需要提出更多要求。我只想指出,如果你想跳过前 18 个字符,那么你应该指定 19 作为 的第二个参数SUBSTRING,因为在 SQL 中,字符串中的字符位置从 1 开始。所以这很有意义并且应该可以很好地工作为你:

SUBSTRING(Serial, 19, 38)
Run Code Online (Sandbox Code Playgroud)

如果您指定 18,那么您将跳过 17 个字符。

George.Palacios 建议使用RIGHTand的解决方案也可以使用LEN,但这两种解决方案的结果可能不同,具体取决于是否可以有尾随空格。可能存在差异的原因是该函数会忽略尾随空格,而不会,这意味着对于带有尾随空格的字符串,结果很可能不是您所期望的。SerialLENRIGHT

让我使用一个带有较短字符串的简单示例来演示。假设最大长度为 10,要跳过的字符数为 4,具体字符串为'abcde  '。(这里的引号只是字符串分隔符,以便您能够看到尾随空格。)如果您这样做了

SUBSTRING('abcde  ', 5, 10)
Run Code Online (Sandbox Code Playgroud)

您将得到'e '结果,因为SUBSTRING将简单地从第 5 个字符开始剪切字符串并包括直到字符串末尾的所有字符。

相反,RIGHT/LEN选项

RIGHT('abcde  ', LEN('abcde  ') - 4)
Run Code Online (Sandbox Code Playgroud)

会屈服' '。该LEN函数将忽略两个尾随空格并返回 5。从 5 中减去 4 得到 1,因此RIGHT将仅返回字符串最右边的一个字符,即空格。

不过,正如我所说,如果Serial永远不能有尾随空格,则任一选项都可以。为了完整起见,让我再推荐一个,它使用STUFF函数:

STUFF(Serial, 1, 18, '')
Run Code Online (Sandbox Code Playgroud)

STUFF函数允许您从给定位置的给定字符串中删除和/或插入另一个子字符串。因此,为了使用此函数跳过 18 个字符,您指定起始位置 1、要删除的 18 个字符和一个空字符串 ( '') 来替换它们。就像SUBSTRING,如果您需要考虑尾随空格,则此解决方案将正确使用尾随空格。

  • 这应该是公认的答案。为什么要在无关紧要的情况下执行获取长度的额外步骤。我没有对其进行分析,但我怀疑这种方法稍微快一点,即使是最低限度的。但即使效率相同,它的代码也更易读/更干净。 (3认同)

Geo*_*ios 6

我会用:

RIGHT(RTRIM(Serial),LEN(Serial)-18) 
Run Code Online (Sandbox Code Playgroud)

这将获取字段的长度并从中减去 18,留下第 18 个字符之后的所有内容。