SQLServer-存储过程中使用字符串和分隔符实现传递数组参数(转)

简介:
< DOCTYPE html PUBLIC -WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml-strictdtd>

一 简介

在高级语言中,很容易编写带有数组参数的函数。但在数据库的存储过程中却没有那么容易,因为存储过程的参数只能以一些基本类型作为参数。我们希望数组作为参数的情况是很常见的,例如有一个表Table(Id int, Data nvarchar(50)),需要向该表一次存入一批数据。如果存储过程以基本数据类型作为参数,定义为InsertData(@data nvarchar(50)), 那么需要循环多次调用该存储过程。

要使存储过程支持数组参数,需做一点变通。可以将需输入的数据转换成字符串,并以某一个分隔符隔开组成一个大的字符串,可以用基本类型text 或 ntext表示。将这个字符串传给存储过程,存储过程内部将其解析,即去掉分隔符,把这批数据放入零时表或某个标变量中,最后批量插入数据表中。

二 解析含有分隔符的字符串生成表变量的流程

SQLServer-存储过程中使用字符串和分隔符实现传递数组参数(转) - netcorner - netcorner的博客

三 解析含有分隔符的字符串生成表变量的用户函数脚本



SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SplitTextToStringArray]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))

DROP FUNCTION [dbo].[SplitTextToStringArray]

GO

-- =============================================

-- Author:      fishinthewind

-- Create date:   7/10/2007

-- Description: Split string variant with type of ntext

-- =============================================

CREATE FUNCTION [dbo].[SplitTextToStringArray]

(

   @text ntext,

   @delimiter char(1)

)

RETURNS @arrayTable TABLE(Idx bigint, [Value] nvarchar(200))

AS

BEGIN

     DECLARE @splitlen int

    SET @splitlen = 4000



    DECLARE @Idx int SET @Idx = 0



    -- 定义取子串的起始位置

    DECLARE @textsplit bigint

    SET @textsplit = 1

    WHILE( @textsplit <= DATALENGTH(@text) )

    BEGIN



        -- 由于许多字符串处理函数无法用于ntext数据类型

        -- 所以需要循环按批处理ntext字符串,一批取出

        -- 个字符放入nvarchar(4000)类型的变量中.

        DECLARE @string nvarchar(4000)

        SELECT @string = SUBSTRING(@text,@textsplit,@splitlen)



        -- 能够取出满个字符

        IF LEN(@string) = @splitlen

        BEGIN

            -- 确保取出的个字符是完整的由分隔符隔开的字符串组合

            DECLARE @lastcomma int

            SELECT @lastcomma = CHARINDEX(@delimiter,REVERSE(@string),1)

            -- 最后一个分隔符后面的字符串不完整,应抛弃

            IF @lastcomma > 0

            BEGIN

                SELECT @string = SUBSTRING(@string,1,@splitlen - @lastcomma)

                -- 设置下一次从@text取字符的起始位置

                SELECT @textsplit = @textsplit + @splitlen - @lastcomma + 1

            END

            -- 最后一个分隔符后面的字符串完整.

            ELSE

            BEGIN

                SELECT @textsplit = @textsplit + @splitlen + 1

            END

        END

        -- 取出不满个字符

        ELSE

        BEGIN

            SELECT @textsplit = @textsplit + @splitlen + 1

        END

      

        -- 解析@string,取出以分隔符为界限的子字符串

        DECLARE @i1 int SET @i1 = 1

        DECLARE @i2 int SET @i2 = 1

        WHILE @i1 <= LEN(@string)

        BEGIN

            SET @i2 = CHARINDEX(@delimiter,@string,@i1+1)

            IF @i2 = 0

                SET @i2 = LEN(@string) + 1

            INSERT @arrayTable (Idx, Value)

            SELECT @Idx, SUBSTRING(@string,@i1,@i2-@i1)

            SET @i1 = @i2 + 1

            SET @Idx = @Idx + 1

        END

    END

    RETURN

END

GO



四 使用该字符串分隔函数的过程脚本



SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[GetCategoryRevisionIds]') AND type in (N'P', N'PC'))

DROP PROCEDURE [dbo].[GetCategoryRevisionIds]

GO



-- =============================================

-- Author:      fishinthewind

-- Create date:   7/10/2007

-- Description: 使用字符分割函数

-- =============================================

CREATE PROCEDURE [dbo].[GetCategoryRevisionIds]

(

   @stringArray ntext

)

AS

BEGIN

    -- SET NOCOUNT ON added to prevent extra result sets from

    -- interfering with SELECT statements.

    SET NOCOUNT ON;



    DECLARE @stringArrayT TABLE(Idx bigint, [Value] nvarchar(200))

    INSERT INTO @stringArrayT(Idx, [Value])

    (

       SELECT Idx, [Value]

       FROM SplitTextToStringArray(@stringArray, ',')

    )



    SELECT * FROM @stringArrayT                  

END

GO
本文转自 netcorner 博客园博客,原文链接:http://www.cnblogs.com/netcorner/archive/2008/03/31/2912171.html   ,如需转载请自行联系原作者
相关文章
|
存储 SQL 数据库
SQL Server存储过程的优缺点
【10月更文挑战第18天】SQL Server 存储过程具有提高性能、增强安全性、代码复用和易于维护等优点。它可以减少编译时间和网络传输开销,通过权限控制和参数验证提升安全性,支持代码共享和复用,并且便于维护和版本管理。然而,存储过程也存在可移植性差、开发和调试复杂、版本管理问题、性能调优困难和依赖数据库服务器等缺点。使用时需根据具体需求权衡利弊。
382 1
|
10月前
|
存储 SQL 数据库连接
C#程序调用Sql Server存储过程异常处理:调用存储过程后不返回、不抛异常的解决方案
本文分析了C#程序操作Sql Server数据库时偶发的不返回、不抛异常问题,并提出了解决思路。首先解析了一个执行存储过程的函数`ExecuteProcedure`,其功能是调用存储过程并返回影响行数。针对代码执行被阻塞但无异常的情况,文章总结了可能原因,如死锁、无限循环或网络问题等。随后提供了多种解决方案:1) 增加日志定位问题;2) 使用异步操作提升响应性;3) 设置超时机制避免阻塞;4) 利用线程池分离主线程;5) 通过信号量同步线程;6) 监控数据库连接状态确保可用性。这些方法可有效应对数据库操作中的潜在问题,保障程序稳定性。
736 11
|
存储 SQL 缓存
SQL Server存储过程的优缺点
【10月更文挑战第22天】存储过程具有代码复用性高、性能优化、增强数据安全性、提高可维护性和减少网络流量等优点,但也存在调试困难、移植性差、增加数据库服务器负载和版本控制复杂等缺点。
593 1
|
存储 SQL 数据库
Sql Server 存储过程怎么找 存储过程内容
Sql Server 存储过程怎么找 存储过程内容
782 1
|
存储 Java 关系型数据库
java调用mysql存储过程
在 Java 中调用 MySQL 存储过程主要借助 JDBC(Java Database Connectivity)。其核心原理是通过 JDBC 与 MySQL 建立连接,调用存储过程并处理结果。具体步骤包括:加载 JDBC 驱动、建立数据库连接、创建 CallableStatement 对象、设置存储过程参数并执行调用。此过程实现了 Java 程序与 MySQL 数据库的高效交互。
|
12月前
|
存储 关系型数据库 MySQL
【YashanDB知识库】MySQL返回结果集的存储过程的改写方法
本文介绍了将MySQL存储过程改写至YashanDB的解决方案。由于MySQL存储过程可直接返回结果集,而YashanDB需通过返回SYS_REF_CURSOR的函数实现类似功能,因此需要对代码进行转换。示例中展示了如何将MySQL存储过程`proc1`改写为YashanDB函数,并调整JDBC应用代码以适配REF_CURSOR输出参数,从而正确获取查询结果。此方法确保了跨数据库场景下的兼容性与功能性。
|
存储 SQL NoSQL
|
存储 SQL 关系型数据库
MySql数据库---存储过程
MySql数据库---存储过程
224 5
|
存储 关系型数据库 MySQL
MySQL 存储过程返回更新前记录
MySQL 存储过程返回更新前记录
259 3
|
存储 SQL 关系型数据库
MySQL 存储过程错误信息不打印在控制台
MySQL 存储过程错误信息不打印在控制台
316 1