【问题标题】:SQL Join Invalid length parameter passed to the LEFT or SUBSTRING functionSQL Join 传递给 LEFT 或 SUBSTRING 函数的长度参数无效
【发布时间】:2016-07-01 16:25:09
【问题描述】:

我的数据库表如下所示:

ID  Value
-------------
1   a1¦aa¦a2
1   b1¦aa¦b2
1   b3¦tt¦b3
2   a2¦aa¦z1
2   b2¦tt¦z2
2   b3¦tt¦z3

我正在尝试用 ¦ 作为有效的断点来拆分每个值:

Select 
    SUBSTRING(MT.Value, 1, CHARINDEX ( '¦' ,MT.Value) - 1) [part1],
    SUBSTRING(MT.Value, CHARINDEX ( '¦' ,MT.Value) + 1, 2) [part2],
    RIGHT(MT.Value,CHARINDEX('¦',REVERSE(MT.Value),0)-1) [part3]
from 
    mytable MT
where 
    MT.id = 1

但后来我尝试包含一个连接以将具有 id2 的记录与 id1 匹配,其中第三部分匹配,SQL Server 抛出错误:

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

代码:

Select 
    SUBSTRING(MT.Value, 1, CHARINDEX ( '¦' ,MT.Value) - 1) [part1],
    SUBSTRING(MT.Value, CHARINDEX ( '¦' ,MT.Value) + 1, 2) [part2],
    RIGHT(MT.Value, CHARINDEX('¦', REVERSE(MT.Value), 0) - 1) [part3],  
    mt1.value
Join 
    mytable mt1 on mt1.ID = 2
                and RIGHT(mt.Value, CHARINDEX('¦', REVERSE(mt.Value), 0) - 1) = SUBSTRING(mt1.Value, 1, CHARINDEX ( '¦' , mt1.Value) - 1)
where 
    MT.id = 1
from 
    mytable MT

有没有人知道我还能怎么做或者我哪里出错了?

【问题讨论】:

  • 缺少表之间的连接链接?
  • 也许只有我,但我不清楚所需的输出
  • 理想情况下,您应该避免在一列中保存多个值。如果可能,请重新访问您的数据库设计。数据库中的每个单元格都应保存一个标量值。您会发现阅读、验证和与数据交互变得更加容易。
  • @destination-data 我完全同意,但我无法做出改变,这不是我的设计。
  • @john cappelletti 所需的输出是一个表格,向我展示了 id1 的最后一部分 = id2 的第一部分,但同时我需要在每次管道损坏时将其拆分为列跨度>

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


【解决方案1】:

您正在对“值”列中的 '¦' 执行 CHARINDEX,然后减去 1。这很可能意味着字符串中至少有 1 条记录中不存在 '¦'。所以你的 CHARINDEX 将 = 零 (0) 然后你减去 1 是一个负数。您不能在子字符串或左函数中使用负数。

一种解决方案是对您的陈述进行包装:

[Part1] = 
    CASE
        WHEN CHARINDEX ( '¦' ,MT.Value) = 0 THEN MT.Value
        ELSE SUBSTRING(MT.Value, 1, CHARINDEX ( '¦' ,MT.Value)-1)
    END

【讨论】:

  • 你是对的,有些值没有 ¦ 因为我忘了在加入时输入完整的标准,感谢您指出显而易见的!
【解决方案2】:

既然您有一个有效的 select 语句,为什么不将它包装在 common table expression (CTE) 中。现在您可以重复使用返回的列。

为了让大家更容易分享您的示例数据,我已将其移至变量中。

    DECLARE @Sample TABLE
    (
        ID      INT,
        [Value] VARCHAR(8)
    )
;


INSERT INTO @Sample
    (
        ID,
        [Value]
    )
VALUES
    (1,'a1¦aa¦a2'),
    (1,'b1¦aa¦b2'),
    (1,'b3¦tt¦b3'),
    (2,'a2¦aa¦z1'),
    (2,'b2¦tt¦z2'),
    (2,'b3¦tt¦z3')
;

我不完全确定我理解了这个要求。所以我最好解释一下我做了什么。此查询返回与ID 2 共享Part1 的所有ID 1。

WITH CTE AS 
    (
        /* Amended OP original query.
         * WHERE clause dropped and 
         * table name replaced with var.
         */
        SELECT
            Id,
            SUBSTRING(MT.Value, 1, CHARINDEX ( '¦' ,MT.Value)-1)    AS [part1],
            SUBSTRING(MT.Value, CHARINDEX ( '¦' ,MT.Value)+1, 2)    AS [part2],
            RIGHT(MT.Value,CHARINDEX('¦',REVERSE(MT.Value),0)-1)    AS [part3]
        FROM
            @Sample MT
    )
SELECT
    *
FROM
    CTE AS cte1
        INNER JOIN CTE AS cte2      ON cte2.part1 = cte1.part1
WHERE
    cte1.ID = 1
    AND cte2.ID = 2
;

【讨论】:

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