servers split sql_SQLServer实现split分割字符串到列

本文介绍了如何在SQLServer中创建一个split函数,将字符串按指定分隔符分割并转换为列。通过示例展示了如何处理单行和多行数据的分割,并探讨了SQLServer在此类操作上的限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

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

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

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

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

ALTER PROC [dbo].[split] @strs VARCHAR(MAX),@delimiter VARCHAR(MAX) AS

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函数,是在其基础上开发的。我们再来看看执行结果:

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

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

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

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

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

-- 删除结果表

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

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

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

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毕竟不够完美,这样的函数系统提供能够最好,自己实现的话遇到太多瓶颈,比如函数不支持动态语句,不能将查询结果传入过程等等。

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

### 关于SQL Server 2005安装时提示已存在同名实例的问题 当遇到SQL Server 2005安装时提示已存在同名实例的情况,可能的原因是目标计算机上已经有一个具有相同名称的SQL Server实例。这可能是之前未完全卸载的旧版本或其他版本的SQL Server造成的。 #### 解决方法一:检查并清理现有实例 可以通过以下方式确认是否存在冲突的实例: 1. 打开命令提示符,输入 `sqlcmd -L` 出当前机器上的所有SQL Server实例。 2. 如果发现有与即将安装的实例名称相同的实例,可以选择更改新安装实例的名称或者移除现有的冲突实例[^1]。 如果决定移除冲突实例,可以按照以下步骤操作: - 使用“添加/删除程序”功能卸载对应的SQL Server实例。 - 删除残留文件夹和注册表项(需谨慎操作)。这些路径通常位于 `%ProgramFiles%\Microsoft SQL Server` 或者类似的目录下。 #### 解决方法二:修改安装设置中的实例名称 在安装过程中,进入实例配置阶段时,手动指定一个新的唯一实例名称而非默认值(如 MSSQLSERVER)。通过这种方式避开与其他已有实例之间的命名冲突问题。 外需要注意的是,在某些情况下即使完成了上述处理仍可能出现错误消息提醒关于端口占用等问题,则应进一步核查网络TCP/IP设定部分是否有重复绑定现象发生,并做相应调整[^2]。 对于更深层次理解SQL及其应用环境构建方面可参阅其发展历程以及具体应用场景描述等内容[^3][^4]。 ```python import os def check_sql_instances(): instances = [] try: result = os.popen('sqlcmd -L').read() lines = result.split('\n') for line in lines: if 'MSSQL' in line.strip(): instances.append(line.strip()) except Exception as e: print(f"Error occurred: {str(e)}") return instances if __name__ == "__main__": sql_servers = check_sql_instances() if sql_servers: print("Detected SQL Servers:") for server in sql_servers: print(server) else: print("No SQL Servers detected.") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值