【问题标题】:How to solve - Invalid length parameter passed to the LEFT or SUBSTRING function如何解决 - 传递给 LEFT 或 SUBSTRING 函数的长度参数无效
【发布时间】:2015-05-13 11:00:06
【问题描述】:

这是我拥有的拆分功能:

CREATE FUNCTION [dbo].[Split2]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH Split(stpos,endpos)
    AS
    (
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos

        UNION ALL

        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
        FROM Split
        WHERE endpos > 0
    )
    SELECT
        'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' =  SUBSTRING(SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos),1,CHARINDEX('$',SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos))-1),
        'UserId' =  SUBSTRING(SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos),CHARINDEX('$',SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos))+1,LEN(SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)))
    FROM Split
)

...我尝试运行此查询:

Declare @String1 nvarchar(max);

SET @String1 = '1$1,0$1,2$2,1$2,0$2,3$3,1$3,0$3,4$4,3$4'

SELECT data, UserId 
FROM dbo.Split2(@String1, ',')
OPTION (maxrecursion 0)

它运行良好,但是当我传递超过 4000 个字符时出现此错误

传递给 LEFT 或 SUBSTRING 函数的长度参数无效。

然后我尝试改变

@String NVARCHAR(4000)

在拆分函数到nvarchar(max);

然后显示

允许的最大值 (4000)。

我如何实现这一点,任何想法都受到高度赞赏。我想拆分长度可能超过 10000 或 20000 个字符的字符串。

【问题讨论】:

  • 问题是你为什么要分割字符串呢?如果要将“数组”传入和传出存储过程,则最好使用表值参数。 Read this article
  • @ZoharPeled 实际上,问题是从这里开始的先生,所以我需要做这样的事情,通过使用选择查询我将存储在临时表中并使用该表进行计算codeproject.com/Questions/883585/…
  • 那么我强烈建议将该树列更改为通过外键约束连接到主表的表。这将为您提供更好的性能和存储大小,因为您的树成员将是整数类型(如果需要,则为大 int)并且您不必拆分任何字符串。
  • 是的,它是通过外键连接的,实际上用户ID是由user_registration表@ZoharPeled引用的
  • 是的,但是树列本身应该在一个单独的表中。在数据库中保留分隔字符串几乎总是错误的方法。在 16 年的编程生涯中,我只需要这样做一次,即使那只是因为使用数据的代码需要逗号分隔的值。我从来没有遇到过任何需要在 sql 中操作分隔字符串的情况,该字符串转换为不会提高代码可读性和性能的表。

标签: sql sql-server sql-server-2008


【解决方案1】:

@String 参数类型更改为NVARCHAR(max) 并将显式转换添加到第一个SELECT 中的0 的bigint,因为CHARINDEX 返回

bigint 如果 expressionToSearch 属于 varchar(max)、nvarchar(max) 或 varbinary(max) 数据类型;否则,int

CREATE FUNCTION [dbo].[Split2]
(
    @String NVARCHAR(max),
    @Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
    WITH Split(stpos,endpos)
    AS
    (
        SELECT CAST(0 AS bigint) AS stpos, CHARINDEX(@Delimiter,@String) AS endpos

        UNION ALL

        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1)
        FROM Split
        WHERE endpos > 0
    )
    SELECT
        'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' =  SUBSTRING(SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos),1,CHARINDEX('$',SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos))-1),
        'UserId' =  SUBSTRING(SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos),CHARINDEX('$',SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos))+1,LEN(SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)))
    FROM Split
)

【讨论】:

  • 谢谢先生,但是字符串有30k个字符,下次可能会改变,它不是固定值,我可以发布字符串值吗?
  • 我的答案中的函数应该可以很好地处理这样的字符串。如果您收到任何错误消息,请尝试让我知道。
【解决方案2】:

SQL Server 字符串限制为 4000 个 Unicode 字符,例如NVARCHAR(MAX)。这就是你的错误的原因。

您可以将其更改为非 Unicode,您将获得 8000,例如VARCHAR(MAX)。

获得更多信息需要您以某种方式控制代码运行时创建的字符串的大小。我不完全清楚它是如何工作的,所以我无法进一步修改它。

【讨论】:

猜你喜欢
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多