SQLServer实现split分割字符串到列

时间:2022-09-05 22:40:05

网上已有人实现sqlserver的split函数可将字符串分割成行,但是我们习惯了split返回数组或者列表,因此这里对其做一些改动,最终实现也许不尽如意,但是也能解决一些问题。

先贴上某大牛写的split函数(来自:Split function in SQL Server to break Comma separated strings,注意我这里将其命名为splitl):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ALTER FUNCTION dbo.splitl (
    @String VARCHAR(MAX),
    @Delimiter VARCHAR(MAX)
) RETURNS @temptable TABLE (items VARCHAR(MAX)) AS
BEGIN
    DECLARE @idx INT=1
    DECLARE @slice VARCHAR(MAX)
    IF LEN(@String) < 1 OR LEN(ISNULL(@String,'')) = 0
        RETURN
    WHILE @idx != 0
    BEGIN
        SET @idx = CHARINDEX(@Delimiter,@String)
        IF @idx != 0
            SET @slice = LEFT(@String,@idx - 1)
        ELSE
            SET @slice = @String
        IF LEN(@slice) > 0
            INSERT INTO @temptable(items) VALUES(@slice)
        SET @String = RIGHT (@String, LEN(@String) - @idx)
        IF LEN(@String) = 0
            BREAK
    END
    RETURN
END

其原理还是比较简单的,一看便知。调用该函数返回的结果是:

1
SELECT FROM dbo.splitl('a#b#c#d','#')

SQLServer实现split分割字符串到列

然而我希望得到的结果是:

1
SELECT 'a' a,'b' b,'c' c,'d' d

SQLServer实现split分割字符串到列

这就要用到sqlserver行转列的技巧,网上有很多方法可以参照。下面真正的split“过程”来了:

1
2
3
4
5
6
7
ALTER PROC [dbo].[split] @strs VARCHAR(MAX),@delimiter VARCHAR(MAXAS
SELECT items,id=IDENTITY(INT,1,1) INTO #ccc FROM dbo.splitl(@strs,@delimiter)
DECLARE @str VARCHAR(MAX)='',@SQL VARCHAR(MAX)='' 
SELECT @str = @str + ',' '[' CONVERT(VARCHAR(MAX),id) + ']' FROM #ccc
SET @SQL = 'SELECT * FROM #ccc PIVOT(MAX(items) FOR id IN(' SUBSTRING(@str,2,LEN(@str)) + ')) b'
EXEC (@SQL)
DROP TABLE #ccc

该过程中使用了pivot语法,参见:使用 PIVOT 和 UNPIVOT

注意这个过程调用了splitl函数,是在其基础上开发的。我们再来看看执行结果:

1
EXEC dbo.split 'a#b#c#d','#'

发现与上面期望的效果完全一致了!

但是这只是针对一行数据做split,如果是查询结果有多行都要分割怎么办呢?

我没有找到办法,因为sqlserver查询语句中不能嵌套过程,只能调用函数,而函数返回的结果集不能是多行。

but..世上无难事,只要写过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
-- 删除结果表
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id=object_id(N'test_result') AND OBJECTPROPERTY(id, N'IsUserTable')=1)
    DROP TABLE test_result
 
-- 建立数据表
CREATE TABLE #tmp (
    id INT NOT NULL IDENTITY(0,1),
    str VARCHAR(MAX)
)
INSERT INTO #tmp SELECT 'a#b#c#d' UNION SELECT 'f#g#h'
 
-- 生成结果表
DECLARE @maxc INT=(SELECT MAX(LEN(str)-LEN(REPLACE(str,'#','')))+1 FROM #tmp)
DECLARE @sql0 VARCHAR(MAX)='CREATE TABLE test_result ('
DECLARE @x INT=0
WHILE @x<@maxc BEGIN
    SET @sql0 = @sql0 + 'a' + CONVERT(VARCHAR(MAX),@x) + ' VARCHAR(MAX),'
    SET @x=@x+1
END
SET @sql0 = SUBSTRING(@sql0,0,LEN(@sql0)) + ')'
EXEC (@sql0)
 
-- 遍历数据表
DECLARE @i INT=0
WHILE @i<(SELECT COUNT(1) FROM #tmp) BEGIN
    DECLARE @strs VARCHAR(MAX)=(SELECT str FROM #tmp WHERE id=@i)
    DECLARE @cols INT=(SELECT LEN(@strs)-LEN(REPLACE(@strs,'#','')))+1
    DECLARE @y INT=0
    DECLARE @sql1 VARCHAR(MAX)='INSERT INTO test_result('
    WHILE @y<@cols BEGIN
        SET @sql1 = @sql1 + 'a' + CONVERT(VARCHAR(MAX),@y) + ','
        SET @y=@y+1
    END
-- -- 分割字符串
    SET @sql1 = SUBSTRING(@sql1,0,LEN(@sql1)) + ') EXEC split "' + @strs + '","#"'
    EXEC (@sql1)
    SET @i=@i+1
END
 
SELECT * FROM test_result

暂时就到此为止八~sqlserver毕竟不够完美,这样的函数系统提供能够最好,自己实现的话遇到太多瓶颈,比如函数不支持动态语句,不能将查询结果传入过程等等。

至于实际应用,将上面这个栗子建立临时数据表的部分替换成要查询的真实表列即可,最后结果如下所示:

SQLServer实现split分割字符串到列

SQLServer实现split分割字符串到列的更多相关文章

  1. Replace是替代 Split分割字符串

    Replace是替代 Split分割字符串string[] ReadText = str.Replace("\r\n", "@").Split('@'); Sp ...

  2. C&num; Split的用法&comma;Split分割字符串

    C# Split的用法,Split分割字符串 分割单个字串:string str="来自张三的亲切问候!;string[] strarry=str.Split(new string[] { ...

  3. C&num;的String&period;Split 分割字符串用法详解的代码

    代码期间,把代码过程经常用的内容做个珍藏,下边代码是关于C#的String.Split 分割字符串用法详解的代码,应该对码农们有些用途. 1) public string[] Split(params ...

  4. java关于split分割字符串&comma;空的字符串不能得到的问题

    java关于split分割字符串,空的字符串不能得到的问题   class T { public static void main(String args[]) { String num[] = ne ...

  5. PLSQL Split分割字符串

    系统自带的split,使用起来方便,但是如果字符串太长,可能会出现异常,这里,我自己写了一个也是该名字,放在自己的包中,引用的时候带包名就好了. --系统自带的函数 /*CURSOR cur_temp ...

  6. String&period;split&lpar;&rpar;分割字符串方法

    split方法的主要用处就是:分割字符串 split方法返回的是数组类型 主要由以下几种用法: 1.比如有一个字符串var str = "bcadeab";对str使用split方 ...

  7. C&num;中使用split分割字符串的几种方法小结

    1.用字符串分隔: using System.Text.RegularExpressions;string str="aaajsbbbjsccc";string[] sArray= ...

  8. C&plus;&plus; split分割字符串函数

    将字符串绑定到输入流istringstream,然后使用getline的第三个参数,自定义使用什么符号进行分割就可以了. #include <iostream> #include < ...

  9. SQL Server 分割字符串转列

    CREATE FUNCTION dbo.sf_DS_SplitNVarchar ( @strValues nvarchar(4000) ) RETURNS @tblStrList TABLE (id ...

随机推荐

  1. 我是如何社工TDbank获取朋友隐私的

    原创 ziwen@beebeeto 转载请保留本行 个人感觉 国外的安全方面对社工的了解和防范并不是很好 即使他们使用社工的时间比我们要长很多 比如 他们的visa在pos机上使用是不需要密码的 而且 ...

  2. 配置管理服务diamond和disconf横向对比

    Diamond则是淘宝开源的一种分布式配置管理服务的实现 disconf是来自百度的分布式配置管理平台,包括百度.滴滴出行.银联.网易.拉勾网.苏宁易购.顺丰科技 等知名互联网公司正在使用! 对比项目 ...

  3. error LNK1123&colon; 转换到 COFF 期间失败&colon; 文件无效或损坏的解决方案

    首先,卸载相关的软件,然后删除所有和virtual studio相关的目录 然后如果还出现该问题,则: Mark一下,解决方法:将嵌入清单设置为"否" 发生场合:在用 C++写一个 ...

  4. material design 图标制作参数

    可用图标的标准不透明度在亮色背景上是54%(#000000).可视等级较低的禁用图标的不透明度应为 26%(#000000). 可用图标的标准不透明度在暗色背景上是 100%(#FFFFFF).可视等 ...

  5. nodejs中的 Cannot read property&&num;39&semi;text&&num;39&semi; of undefined 问题

    接触nodejs时间不久,最近遇到了这个问题,经过查阅资料以及百度终于解决了.

  6. js传参java接收乱码解决方案

    js传参处理 encodeURI(encodeURI(name)); java接收处理 URLDecoder.decode(request.getParameter("name") ...

  7. &lbrack;Swift&rsqb;LeetCode210&period; 课程表 II &vert; Course Schedule II

    There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may have prereq ...

  8. JID介绍

    JID: 一个XMPP实体的地址称为Jabber Identifier或JID,作用类似于IP地址.一个合法的JID包括节点名,域名资源名,其格式为:jid=[node'@']domain['/'re ...

  9. 黄聪:xampp运行MySQL shutdown unexpectedly解决方案

    相信不少喜欢WordPress的朋友和我一样,会用xampp在本地搭建一个网站学习调试,但是在用的过程中也会遇到些麻烦,毕竟我们都是小白,今天就分享一个xampp运行MySQL数据时出现 Error: ...

  10. &lbrack;20180627&rsqb;测试bbed是否支持管道命令&period;txt

    [20180627]测试bbed是否支持管道命令.txt --//测试bbed是否支持管道命令.txt 1.环境:SCOTT@test01p> @ ver1PORT_STRING         ...