MSSQL - 创建 table 函数,return 子字符串

MSSQL - Create table function, return substring

我需要创建这个 table 函数。该函数需要 return 来自传递参数的单个单词,例如:hello、hhuu、value

table函数应该return:

hello,
hhuu, 
value

但是我总是遇到一些错误,请你帮帮我好吗?

请看这篇文章: http://www.codeproject.com/Tips/625872/Convert-a-CSV-delimited-string-to-table-column-in

您可以使用 ' ' (space) 作为分隔符。

SELECT * FROM dbo.CSVtoTable('hello, hhuu, value', ' ')

你可以这样写:

DECLARE @input_char VARCHAR(255)
SET @input_char =  'hello, hhuu, value'

;WITH cte AS (
    SELECT        
        CAST('<r>' + REPLACE(@input_char, ' ', '</r><r>') + '</r>' AS XML) AS input_char
)
SELECT     
   rtrim( LTRIM (xTable.xColumn.value('.', 'VARCHAR(MAX)')) ) AS input_char
FROM cte
CROSS APPLY input_char.nodes('//r') AS xTable(xColumn) 

下面这个功能我用过很多次了。有点冗长请见谅,但对我来说已经成为了一个很好的工具。

CREATE Function [dbo].[ParseText2Table] 
 (
 @p_SourceText  varchar(MAX)
 ,@p_Delimeter varchar(100) = ',' --default to comma delimited.
 )
RETURNS @retTable TABLE 
 (
  POSITION  INT 
 ,Int_Value bigint 
 ,Num_value REAL--Numeric(18,3)
 ,txt_value varchar(MAX)
 )
AS


BEGIN

 DECLARE @tmpTable TABLE
  (
  Position2  INT IDENTITY(1,1) PRIMARY KEY
 ,Int_Value bigint 
 ,Num_value REAL--Numeric(18,3)
 ,txt_value varchar(MAX)
 )

 DECLARE @w_Continue  INT
  ,@w_StartPos  INT
  ,@w_Length  INT
  ,@w_Delimeter_pos INT
  ,@w_tmp_int  bigint
  ,@w_tmp_num  REAL--numeric(18,3)
  ,@w_tmp_txt   varchar(MAX)
  ,@w_Delimeter_Len INT

 IF len(@p_SourceText) = 0
 BEGIN
  SET  @w_Continue = 0 -- force early exit
 END
 ELSE
 BEGIN
-- if delimiter is ' ' change
 IF @p_Delimeter = ' ' 
 BEGIN
  SET @p_SourceText = replace(@p_SourceText,' ','ÿ')
  SET @p_Delimeter = 'ÿ'
 END
 -- parse the original @p_SourceText array into a temp table
  SET  @w_Continue = 1
  SET @w_StartPos = 1
  SET @p_SourceText = RTRIM( LTRIM( @p_SourceText))
  SET @w_Length   = DATALENGTH( RTRIM( LTRIM( @p_SourceText)))
  SET @w_Delimeter_Len = len(@p_Delimeter)
 END

 WHILE @w_Continue = 1
 BEGIN
  SET @w_Delimeter_pos = CHARINDEX( @p_Delimeter
      ,(SUBSTRING( @p_SourceText, @w_StartPos
      ,((@w_Length - @w_StartPos) + @w_Delimeter_Len)))
      )

  IF @w_Delimeter_pos > 0  -- delimeter(s) found, get the value
  BEGIN
   SET @w_tmp_txt = LTRIM(RTRIM( SUBSTRING( @p_SourceText, @w_StartPos 
        ,(@w_Delimeter_pos - 1)) ))
   IF dbo.isReallyNumeric(@w_tmp_txt) = 1 --and not @w_tmp_txt in('.', '-', '+', '^')
   BEGIN
    --set @w_tmp_int = cast( cast(@w_tmp_txt as real) as bigint)--numeric) as bigint)
    SET @w_tmp_int = CASE WHEN (CAST(@w_tmp_txt AS REAL) BETWEEN -9223372036854775808 AND 9223372036854775808) THEN  CAST( CAST(@w_tmp_txt AS REAL) AS bigint) ELSE  NULL END
    SET @w_tmp_num = CAST( @w_tmp_txt AS REAL)--numeric(18,3))
   END
   ELSE
   BEGIN
    SET @w_tmp_int =  NULL
    SET @w_tmp_num =  NULL
   END
   SET @w_StartPos = @w_Delimeter_pos + @w_StartPos + (@w_Delimeter_Len- 1)
  END
  ELSE -- No more delimeters, get last value
  BEGIN
   SET @w_tmp_txt = LTRIM(RTRIM( SUBSTRING( @p_SourceText, @w_StartPos 
      ,((@w_Length - @w_StartPos) + @w_Delimeter_Len)) ))
   IF dbo.isReallyNumeric(@w_tmp_txt) = 1 --and not @w_tmp_txt in('.', '-', '+', '^')
   BEGIN
    --set @w_tmp_int = cast( cast(@w_tmp_txt as real) as bigint)--as numeric) as bigint)
     SET @w_tmp_int = CASE WHEN (CAST(@w_tmp_txt AS REAL) BETWEEN -9223372036854775808 AND 9223372036854775808) THEN  CAST( CAST(@w_tmp_txt AS REAL) AS bigint) ELSE  NULL end
    SET @w_tmp_num = CAST( @w_tmp_txt AS REAL)--numeric(18,3))
   END
   ELSE
   BEGIN
    SET @w_tmp_int =  NULL
    SET @w_tmp_num =  NULL
   END
   SELECT @w_Continue = 0
  END
  INSERT INTO @tmpTable VALUES( @w_tmp_int, @w_tmp_num, @w_tmp_txt )
 END

INSERT INTO @retTable SELECT   Position2, Int_Value ,Num_value ,txt_value FROM @tmpTable

RETURN
END

下面还有上面的支持函数:

CREATE FUNCTION dbo.isReallyInteger  
(  
    @num VARCHAR(64)  
)  
RETURNS BIT  
BEGIN  
    IF LEFT(@num, 1) = '-'  
        SET @num = SUBSTRING(@num, 2, LEN(@num))  

    RETURN CASE  
    WHEN PATINDEX('%[^0-9-]%', @num) = 0  
        AND CHARINDEX('-', @num) <= 1  
        AND @num NOT IN ('.', '-', '+', '^') 
        AND LEN(@num)>0  
        AND @num NOT LIKE '%-%' 
    THEN  
        1  
    ELSE  
        0  
    END  
END 

CREATE  FUNCTION dbo.isReallyNumeric  
(  
    @num VARCHAR(64)  
)  
RETURNS BIT  
BEGIN  
    IF LEFT(@num, 1) = '-'  
        SET @num = SUBSTRING(@num, 2, LEN(@num))  

    DECLARE @pos TINYINT  

    SET @pos = 1 + LEN(@num) - CHARINDEX('.', REVERSE(@num))  

    RETURN CASE  
    WHEN PATINDEX('%[^0-9.-]%', @num) = 0  
        AND @num NOT IN ('.', '-', '+', '^') 
        AND LEN(@num)>0  
        AND @num NOT LIKE '%-%' 
        AND  
        (  
            ((@pos = LEN(@num)+1)  
            OR @pos = CHARINDEX('.', @num))  
        )  
    THEN  
        1  
    ELSE  
    0  
    END  
END 

使用示例:

--Single Character Delimiter
--select * from dbo.ParseText2Table('100|120|130.56|Yes|Cobalt|Blue','|')
--select txt_value from dbo.ParseText2Table('100 120 130.56 Yes Cobalt Blue',' ') where Position = 3
--select * from dbo.ParseText2Table('100,120,130.56,Yes,Cobalt,Blue,,',',')

/*
POSITION    Int_Value   Num_value            txt_value 
----------- ----------- -------------------- --------------
1           100         100.000              100
2           120         120.000              120
3           131         130.560              130.56
4           NULL        NULL                 Yes
5           NULL        NULL                 Cobalt Blue
*/