• T-SQL——将字符串转为单列


    shanzm-2023年2月22日

    0. 背景

    代码中执行存储过程,参数是多个且不确定数量,期望SQL查询时使用该参数作为IN的筛选条件

    比如说,具体参数@Ids="1,2,3,4",

    期望在存储过程中,实现 select * from Table where id In @Ids

    直接这样写会报错

    (当然可以使用动态sql 进行拼接,但不需要这么做),而是将传递的参数分裂为单列的行记录!



    1. 使用STRING_SPLIT函数

    • Sql Server在2016版本中支持使用STRING_SPLIT函数

      • 可以将字符串按照分隔符,切割成一个数据表
    • 若是低版本数据使用提示对象名 'STRING_SPLIT' 无效。

    SELECT * FROM STRING_SPLIT('1,2,3,4,5', ',');
    
    --结果:
    value
    -------------
    1
    2
    3
    4
    5
    


    2. 自定义分裂函数

    • 实现方式1:基于字符串操作

      • 将目标字符串末尾拼接上一个分隔符
      • 从字符串第一个位置开始查询分隔符在字符串中第一次出现的位置索引
      • 从左截取(第一个分隔符索引-1)长度的字符串,此外分裂出的第一个结果
      • 将目标字符串从第一个分隔符之前的替换为空
      • 循环上述2~4步骤
    -- ======================================================
    -- Author:		shanzm
    -- Create date: 2021年6月30日 15:52:02
    -- Description:	将指定字符串按照指定的分裂符分裂为单列表            
    -- ======================================================
    ALTER FUNCTION [dbo].[funGetSplitStr]
    (
        @Str VARCHAR(8000),       --目标字符串,形如"a,b,c"
        @StrSeprate VARCHAR(1)    --分隔符,形如","
    )
    RETURNS @temp TABLE           --返回表值变量,只有一列F1
    (
        F1 VARCHAR(100)
    )
    AS
    BEGIN
        DECLARE @ch AS VARCHAR(100);
        SET @Str = @Str + @StrSeprate;
        WHILE (@Str <> '')
        BEGIN
            SET @ch = LEFT(@Str, CHARINDEX(@StrSeprate, @Str, 1) - 1);
            INSERT @temp
            VALUES
            (@ch);
            SET @Str = STUFF(@Str, 1, CHARINDEX(@StrSeprate, @Str, 1), '');
        END;
        RETURN;
    END;
    
    
    
    • 实现方式2:基于XML
    -- ======================================================
    -- Author:		shanzm
    -- Create date: 2021年6月30日 15:52:02
    -- Description:	将指定字符串按照指定的分裂符分裂为单列表            
    -- ======================================================
    CREATE FUNCTION dbo.funGetSplitStr2
    (
        @str varchar(1000),
        @strSperate varchar(10)
    )
    RETURNS @tableVar TABLE
    (
        F1 VARCHAR(100)
    )
    AS
    BEGIN
        DECLARE @xmlstr XML;
        --SET ARITHABORT ON;
        SET @xmlstr = CONVERT(XML, '' + REPLACE(@str, @strSperate, '') + '');
        --SELECT @xmlstr;
    
        INSERT INTO @tableVar
        SELECT F1 = N.v.value('.', 'varchar(100)') FROM @xmlstr.nodes('/root/v') N(v);
    	RETURN;
    END;
    GO
    
    
    --测试
    SELECT * FROM  funGetSpliterStr2('1.2.3','.')
    
    --结果
    
    F1
    ---------
    1
    2
    3
    
    (3 行受影响)
    


    3. 使用示例

    代码中传递的参数@Ids="1,2,3,4",执行存储过程作为筛选条件

    这里任意使用一个测试表Company,该表有一个Id字段,存储过程简单的演示了Ids字符串进行查询

    • 创建测试存储过程
    CREATE PROCEDURE [dbo].[proTest]
    @Ids VARCHAR(500)
    AS
    BEGIN
        SELECT *
        FROM dbo.Company
        WHERE Id IN
              (
                  SELECT F1 FROM dbo.funGetSplitStr(@Ids, ',')
              );
    END;
    
    
    EXEC dbo.proTest @Ids = '1,3'; 
    
  • 相关阅读:
    Java 集合 - Map 接口
    Xilinx ISE系列教程(7):QSPI编程文件的生成和烧录
    使用 Django Rest Framework 构建强大的 Web API
    金仓数据库KingbaseES数据库参考手册(服务器配置参数4. 连接和认证)
    零基础学习Linux系统计划任务cron
    npm ,yarn 更换使用国内镜像源,淘宝源
    计算机毕设 SpringBoot+Vue校园网新闻系统 新闻推荐系统 新闻发布管理系统Java Vue MySQL数据库 远程调试 代码讲解
    单点登录SSO的含义
    使用vmware搭建openwrt开发环境
    SHAP - 解释机器学习
  • 原文地址:https://www.cnblogs.com/shanzhiming/p/17143951.html