T-SQL技巧收集——拆分字符串

简介: 原文: T-SQL技巧收集——拆分字符串          在开发中,很多时候都需要处理拆分字符串的操作。下面收集了几种方法供大家分享,其中的逗号可以改为多种有需要的符号,但是不能针对多种符号同时存在的例子。
原文: T-SQL技巧收集——拆分字符串

         在开发中,很多时候都需要处理拆分字符串的操作。下面收集了几种方法供大家分享,其中的逗号可以改为多种有需要的符号,但是不能针对多种符号同时存在的例子。有待各位补充:

说明:

将字符串转换为正规化的数据表,可以使用多种方法实现,比如前端程序处理、游标、数据库循环函数,都是常用的技巧。

对于处理这些问题,比较好的思路就是使用SUBSTRING函数取出字符串,然后使用CHARINDEX函数定位。最后搭配排序函数完成拆分。

对于2005以后,可以使用CTE来实现。另外可以自定义一个函数处理。搭配输入分隔符与字符串,然后以TABLE方式返回。

解决方法:

下面是这4种方式的示例:

备注:首先针对原始字符串,可以使用BULKINSERT 后者BCP命令甚至直接INSERT语句,把原始数据导入数据表。以下语句是待处理的数据产生脚本,有业务代号和业务员订单:

为了输出每个业务员的每笔订单序号,所以用循环产生一个数据表,储存指定数量的序号。

接下来就是上面提到的4种方式的实现:

USE tempdb

GO

--建立数据表存储原始数据:

CREATE TABLE Arrays

   (

      salesID VARCHAR(10) NOT NULL ,

      salesOrd VARCHAR(8000) NOT NULL

    )

GO

--注意:下面insert 语句中逗号后面有一个空格

INSERT  INTO Arrays

VALUES ( 'A', '20, 223, 2544' ) ;

INSERT  INTO Arrays

VALUES ( 'B', '30, 23433, 28' ) ;

INSERT  INTO Arrays

VALUES ( 'C', '12, 10' ) ;

INSERT  INTO Arrays

VALUES ( 'D', '4, 6, 45678, 2' ) ;

GO

 

--通过循环产生存储指定数量的序号的表

CREATE TABLE Nums

   (

      c1 INT NOT NULL

            PRIMARY KEY

    ) ;

GO

--产生数据

DECLARE @i INT

SET @i = 1

WHILE @i <= 8000

    BEGIN

        INSERT  INTO Nums

        VALUES  ( @i )

        SET @i = @i + 1

    END

 

 

--方法一:适合2005以上版本使用。使用ROW_NUBMER函数

 

SELECT  salesID [业务编号] ,

        ROW_NUMBER() OVER ( PARTITION BY salesID ORDER BY c1 ) AS [序号] ,

        SUBSTRING(salesOrd, c1, CHARINDEX(', ', salesOrd + ', ', c1) - c1) AS []

FROM    Arrays

        JOIN Nums ON c1 <= LEN(salesOrd)

                     ANDSUBSTRING(', ' + salesOrd, c1, 1) = ', '

ORDER BY salesID ,

        [序号]

       

       

--方法二:适用于任何版本

SELECT  salesID [业务编号] ,

        c1 - LEN(REPLACE(LEFT(salesOrd, c1), ', ', '')) + 1 [序号] ,

        SUBSTRING(salesOrd, c1, CHARINDEX(', ', salesOrd + ', ', c1) - c1) AS []

FROM    arrays

        JOIN Nums ON c1 <= LEN(salesOrd)

                     ANDSUBSTRING(', ' + salesOrd, c1, 1) = ', '

ORDER BY salesID ,

        [序号]

       

       

--方式三:适用于2005以上版本,使用CTE实现:

;

WITH    SplitCTE

          AS ( SELECT   salesID ,

                        1 AS pos ,

                        1 AS startpos ,

                        CHARINDEX(', ', salesOrd + ', ') - 1 AS endpos

              FROM    dbo.Arrays

              WHERE   LEN(salesOrd) > 0

              UNION ALL

              SELECT  Prv.salesID ,

                        Prv.pos+ 1 ,

                        Prv.endpos+ 2 ,

                        CHARINDEX(', ', CUR.salesOrd + ', ', Prv.endpos + 2)

                        - 1

              FROM    SplitCTE ASPrv

                        JOIN dbo.Arrays AS Cur ON CUR.salesID = Prv.salesID

                                                 AND CHARINDEX(', ',

                                                             cur.salesOrd

                                                             + ', ',

                                                             Prv.endpos + 2) > 0

            )

    SELECT  A.salesID AS [业务编号] ,

           pos [序号] ,

           CAST(SUBSTRING(salesOrd, startpos, endpos - startpos + 1) AS INT) AS []

    FROM    dbo.Arrays AS a

           JOIN SplitCTEAS S ON S.salesID = A.salesID

    ORDER BY A.salesID ,

           pos

 GO

 

    --方法4:使用自定义函数

CREATE FUNCTION dbo.fn_split( @orders AS VARCHAR(MAX) )

RETURNS TABLE

AS

    RETURN

    SELECT  c1 - LEN(REPLACE(LEFT(@orders, c1), ', ', '')) + 1 AS [序号] ,

           SUBSTRING(@orders, c1, CHARINDEX(', ', @orders + ', ', c1) - c1) AS []

    FROM    dbo.Nums

    WHERE   c1 <= LEN(@orders)

           AND SUBSTRING(', ' + @orders, c1, 1) = ', ' ;

    GO

   

    --然后使用cross apply技巧,合并分解字符串

SELECT  salesID ,

        B.*

FROM    Arrays a

        CROSS APPLY dbo.fn_split(a.salesOrd) b

    GO

通过一下执行计划的开销可以看到CTE方法的实现开销最小,所以建议使用这种方式处理:

 

目录
相关文章
|
SQL 数据库
达梦(DM) SQL数据及字符串操作
继续讲述DM数据库Sql操作
|
8月前
|
SQL Java 数据库连接
MyBatis动态SQL字符串空值判断,这个细节99%的程序员都踩过坑!
本文深入探讨了MyBatis动态SQL中字符串参数判空的常见问题。通过具体案例分析,对比了`name != null and name != &#39;&#39;`与`name != null and name != &#39; &#39;`两种写法的差异,指出后者可能引发逻辑混乱。为避免此类问题,建议在后端对参数进行预处理(如trim去空格),简化MyBatis判断逻辑,提升代码健壮性与可维护性。细节决定成败,严谨处理参数判空是写出高质量代码的关键。
1153 0
|
SQL 存储 Serverless
SQL语句拆分时间字段的技巧与方法
在数据库操作中,经常需要处理时间数据
1011 1
|
SQL XML JSON
在 SQL Server 中使用字符串转义
【8月更文挑战第5天】
1571 7
在 SQL Server 中使用字符串转义
|
SQL Oracle 关系型数据库
SQL语句中的引号使用技巧:正确处理字符串与标识符
在编写SQL语句时,引号的使用是一个基础且重要的环节
1950 0
|
JSON 数据格式 SQL
SQL开发问题之直接使用join方法在处理字符串类型属性时可能会遇到性能问题如何解决
SQL开发问题之直接使用join方法在处理字符串类型属性时可能会遇到性能问题如何解决
147 8
|
SQL 存储 关系型数据库
SQL字符串查询有哪些坑?
本文通过创建一个包含不同格式姓名数据的表格,探讨了MySQL中字符排序规则(Collation)的影响。通过使用不区分大小写和空格的查询条件,文章演示了如何获取所有插入的记录,并解释了排序规则中&quot;_ci&quot;、&quot;_cs&quot;及&quot;_bin&quot;的区别。此外,还强调了在数据处理过程中,应考虑大小写敏感性和字符串前后空格的问题,以防导致统计或比较上的错误。最后,提供了Go语言中处理这类问题的方法,如使用`strings.EqualFold()`进行不区分大小写的字符串比较,以及使用`strings.TrimSpace()`去除字符串两端的空白字符。
210 1
|
SQL 关系型数据库 MySQL
MySQL根据某个字段包含某个字符串或者字段的长度情况更新另一个字段的值,如何写sql
MySQL根据某个字段包含某个字符串或者字段的长度情况更新另一个字段的值,如何写sql
683 0
|
SQL 数据库 Python
【Python】已完美解决:(executemany()方法字符串参数问题)more placeholders in sql than params available
【Python】已完美解决:(executemany()方法字符串参数问题)more placeholders in sql than params available
306 1
|
SQL 数据采集 存储
"揭秘SQL Server中REPLACE函数的神奇力量!一键替换字符串,解锁数据处理的无限可能,你还在等什么?"
【8月更文挑战第20天】SQL Server 的 REPLACE 函数是处理字符串的强大工具,用于在查询中替换字符串的部分内容。基本语法为 `REPLACE(string_expression, string_pattern, string_replacement)`。例如,可将员工邮箱从 `@example.com` 替换为 `@newdomain.com`。支持多级嵌套替换与变量结合使用,适用于动态生成查询。注意大小写敏感性及全局替换特性。掌握 REPLACE 函数能有效提升数据处理能力。
790 0