如何从 MSSQL 中的 STRING_SPLIT 函数启用序数

Ras*_*usM 14 sql-server ssms

我正在尝试使用 Microsoft SQL Server 2019 中的 STRING_SPLIT 函数。如果我只输入两个参数,该函数就可以工作,但由于我想从字符串中提取特定元素,所以我想启用序数。当我将第三个参数添加到 STRING_SPLIT 函数时,它返回

消息 8144,级别 16,状态 3,第 5 行 过程或函数 STRING_SPLIT 指定了太多参数。

我不明白我做错了什么,因为将鼠标悬停在 STRING_SPLIT 函数上清楚地表明该函数可以将第三个参数作为 int 。

我的SQL代码如下

SELECT *
FROM STRING_SPLIT('[Control Structure].Root.NP_02.ABC01_02_03.Applications.Prototype.Control Modules.ABC060V.ABC060VXFR2','.',1)
WHERE ORDINAL = 4
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 17

您无法启用它,因为它在 SQL Server 2019 中不可用(并且几乎肯定不会向后移植)。

问题是SSMS的IntelliSense/工具提示编码没有基于版本的条件逻辑,并且代码领先于引擎。目前,该功能仅在 Azure SQL 数据库、托管实例和 Synapse 中可用。

文档中:

目前,enable_ordinal参数和ordinal输出列仅在 Azure SQL 数据库、Azure SQL 托管实例和 Azure Synapse Analytics(仅限无服务器 SQL 池)中受支持。

更多背景:

您可以做的是创建自己的内联表值 UDF,它提供相同类型的序数输出(并使其返回相同的输出,以便STRING_SPLIT以后轻松更改)。这有很多变体;这是一个:

CREATE FUNCTION dbo.SplitStrings_Ordered
(
    @List       nvarchar(max),
    @Delimiter  nvarchar(255)
)
RETURNS TABLE
AS
    RETURN (SELECT value = Item ,
      ordinal = ROW_NUMBER() OVER (ORDER BY Number), 
    FROM (SELECT Number, Item = SUBSTRING(@List, Number, 
      CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number)
     FROM (SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id])
      FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2) AS n(Number)
      WHERE Number <= CONVERT(INT, LEN(@List))
      AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter)) = @Delimiter
    ) AS y);
GO
Run Code Online (Sandbox Code Playgroud)

另一种更简单的方法是使用 JSON,我忘记了我最近在本技巧中写过:

CREATE FUNCTION dbo.SplitStrings_Ordered
(
  @List      nvarchar(max),
  @Delimiter nchar(1)
)
RETURNS table WITH SCHEMABINDING
AS
  RETURN
  (
    SELECT value, ordinal = [key]
    FROM OPENJSON(N'["' + REPLACE(@List, @Delimiter, N'","') + N'"]') AS x
  );
GO
Run Code Online (Sandbox Code Playgroud)

另外,如果您只是想获取 (1-)4 部分名称中的最后一个序数,并且每个部分 <= 128 个字符,您可以使用PARSENAME()

DECLARE @str nvarchar(512) = N'here is one.here is two.and three.and four';

SELECT p1 = PARSENAME(@str, 4),
       p2 = PARSENAME(@str, 3),
       p3 = PARSENAME(@str, 2),
       p4 = PARSENAME(@str, 1);
Run Code Online (Sandbox Code Playgroud)

输出:

p1 p2 p3 p4
这是一个 这是两个 和三个 和四个