【问题标题】:SQL server tokenizerSQL 服务器分词器
【发布时间】:2015-11-05 18:39:59
【问题描述】:

SQL server 有没有办法创建一个函数,让下面的字符串 'ABC,DEF,GHI' 输出值 3。

然后是否有可能有一个函数允许您指定要输出的字符串的标记。 所以输入将是您想要返回的字符串和令牌。 输入:('ABC,DEF,GHI',2) 输出:DEF

【问题讨论】:

  • 阅读How to Ask。不要马虎。
  • 欢迎使用非原子列,逗号分隔字符串和拆分功能。 SO(UDF,XML + CROSS APPLY,SUBSTRING)中有很多选择你需要的
  • 最好的选择是首先不存储分隔数据。
  • T-SQL split string的可能重复

标签: sql sql-server tokenize


【解决方案1】:

第一个问题

declare @token varchar(20)
set @token = 'ABC,DEF,GHI'

select len(@token) - len(replace(@token ,',','')) + 1

【讨论】:

    【解决方案2】:

    这比你写的代码要短得多:

    简短的解释:通过将, 替换为</x><x>,我们只需在前面添加一个<x>,在末尾添加一个</x> - 瞧! - 我们有 XML。

    XML 易于索引。您必须使用 XQuery 函数 sql:variable() 将变量索引放入 XPath。

    DECLARE @string VARCHAR(MAX)='ABC,DEF,GHI'; 
    DECLARE @index INT=2;
    
    WITH AsXML AS 
    (
        SELECT CAST('<x>' + REPLACE(@string,',','</x><x>') + '</x>' AS XML) AS Splitted
    )
    SELECT Splitted.value('/x[sql:variable("@index")][1]','varchar(max)')
    FROM AsXML 
    

    编辑:在这里,您可以找到一个使用这种方法作为函数的完整工作示例。

    CREATE FUNCTION dbo.Tokenizer
    (
         @string VARCHAR(MAX)
        ,@index INT
    )
    RETURNS VARCHAR(MAX)
    AS
    BEGIN
        DECLARE @RetVal VARCHAR(MAX);
    
        WITH AsXML AS 
        (
            SELECT CAST('<x>' + REPLACE(@string,',','</x><x>') + '</x>' AS XML) AS Splitted
        )
        SELECT @RetVal = Splitted.value('/x[sql:variable("@index")][1]','varchar(max)')
        FROM AsXML;
    
        RETURN @RetVal; 
    END
    GO
    
    SELECT dbo.Tokenizer( 'ABC,DEF,GHI',2); --Returns "DEF"
    GO
    
    --Clean up
    DROP FUNCTION dbo.Tokenizer; 
    

    【讨论】:

    • 你能帮忙把它转换成一个函数吗?
    • @dog2bert,请查看我的回答中的编辑。并且:请注意,在这里给出答案的专业人士渴望获得声誉积分。如果您对有用的答案进行投票,那将是非常好的 - 如果一个答案帮助您解决了您的问题 - 您应该将其标记为已接受的答案,这将向其他人表明该问题已解决。如果答案没有帮助,请发表评论,谢谢!顺便说一句:我刚刚把你推到了神奇的 15 个代表点上,让你能够对答案进行投票。请也通过您的旧问题。您没有投票或接受其中任何一个...
    【解决方案3】:

    这个函数可以满足我第 2 部分的需要

    CREATE FUNCTION dbo.itemAtIndexInASplitString( @stringToSplit VARCHAR(MAX), @delimiter VARCHAR(5), @indexToReturn int)
    RETURNS
    varchar(max)
    AS
    BEGIN
    DECLARE @returnList TABLE ([ID] int, [Name] [nvarchar] (500))
    DECLARE @name NVARCHAR(255)
    DECLARE @pos INT
    DECLARE @index INT
    DECLARE @return_value varchar(max)
    SET @index = 0
    SET @return_value = null
    
    WHILE CHARINDEX(@delimiter, @stringToSplit) > 0
    BEGIN
    SELECT @pos  = CHARINDEX(@delimiter, @stringToSplit)  
    SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
    
    INSERT INTO @returnList 
    SELECT @index, @name
    
    SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
    SET @index = @index + 1 END
    
    INSERT INTO @returnList
    SELECT @index, @stringToSplit
    
    SELECT @return_value = Name from @returnList where [ID] = @indexToReturn
    
    RETURN @return_value
    END
    GO
    

    【讨论】:

    • 您的代码正在运行,但远非复杂......如果可能的话,应该避免使用 SQL 中的过程方法。这是一种基于集合的语言......这意味着:避免循环(WHILE)、游标和其他“一步一步”的概念。我发布了您第二个问题的答案。你已经有了第一个...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 2022-12-19
    • 2013-01-01
    • 2015-11-03
    • 2013-03-18
    相关资源
    最近更新 更多