T-SQL如何将逗号分隔的数字字符串转换为整数

5
我收到一个错误信息:“当将nvarchar值'23,24,3,45,91,'转换为int数据类型时,转换失败。”该错误似乎发生在ON子句中。E.ID是一个整数字段,而F.LegalIssue是一个由逗号分隔的整数varchar字段。以下是代码,包含该错误。
SELECT F.[FDTitle], E.PrimaryOpID as [FD Primary OP ID], F.County as [FD County], F.Status as [FD Status], F.IssueDate as [FD Date]
FROM [dbo].[tbl_FinalDetMain] F
LEFT OUTER JOIN [dbo].[tbl_lk_Exemptions_FD] E ON E.ID = F.LegalIssue
WHERE F.[FDNbr] = '2013-0041'

我已经尝试了以下代码中的on语句,但它只返回一个整数值,而不是整个整数字符串。
E.ID = cast(LEFT(F.LegalIssue,PATINDEX('%[^0-9]%',F.LegalIssue)-1) as int)

结果应包括由逗号分隔的五个整数。

8
请停止将逗号分隔的列表存储在单个列中。您可能认为这是一个聪明而有用的设计,但它会带来更多问题而不是解决问题。数据库不是JSON容器! - Aaron Bertrand
3个回答

9
如果LegalIssue包含逗号分隔的数字字符串,那么你真的需要一个关联表。如果没有,这里有一种方便(但不高效)的方法来执行连接:
SELECT F.[FDTitle], E.PrimaryOpID as [FD Primary OP ID], F.County as [FD County],
       F.Status as [FD Status], F.IssueDate as [FD Date]
FROM [dbo].[tbl_FinalDetMain] F LEFT OUTER JOIN
      [dbo].[tbl_lk_Exemptions_FD] E
      ON ','+F.LegalIssue+',' like '%,'cast(E.ID as varchar(255))+',%'
WHERE F.[FDNbr] = '2013-0041';

这将在列表前后添加逗号,以避免冲突,比如在"1,100,1000"中查找"10"。


3
使用xml数据类型,你可以像这样将字符串分解为整数。我认为这是一个很好的用户定义函数的候选方案 :-)
declare @test varchar(max)

set @test = '1,2,3,4,5'

select 
     T2.item.value('(./text())[1]','int') 
from
     (select convert(xml,'<items><t>'+replace(@test,',','</t><t>')+'</t></items>') as xmldoc)
as xmltable
     CROSS APPLY xmltable.xmldoc.nodes('/items/t') as T2(item) 

1
你需要将 F.LegalIssue 规范化为多行,或者使用 LIKE。类似这样:
    CAST(E.ID A VARCHAR(50)) = F.LegalIssue
OR  F.LegalIssue LIKE CAST(E.ID A VARCHAR(50)) + ',%'
OR  '%,' + F.LegalIssue LIKE CAST(E.ID A VARCHAR(50)) + ',%'
OR  '%,' + F.LegalIssue LIKE CAST(E.ID A VARCHAR(50))

正如你所见,表的实际设计是问题的关键。您应该避免当前的设计,选择一个“一对多”或“多对多”的设计。

这里是一个使用递归CTE展开值的DEMO

SQL Fiddle DEMO

创建测试表和数据

CREATE TABLE Tada(
  ID INT,
  SomeCommaString VARCHAR(50)
  )
INSERT INTO Tada Values (1, '10'),(2,'5,6,12,16')

平坦化表格

;WITH Vals AS (
  SELECT 
      ID,
      CASE
          WHEN CHARINDEX(',',SomeCommaString) = 0
            THEN SomeCommaString
          WHEN CHARINDEX(',',SomeCommaString) > 0
            THEN LEFT(SomeCommaString,CHARINDEX(',',SomeCommaString) - 1)
      END Val,

      CASE
          WHEN CHARINDEX(',',SomeCommaString) > 0
            THEN RIGHT(SomeCommaString,LEN(SomeCommaString) - CHARINDEX(',',SomeCommaString))
          ELSE NULL
      END Remainder
  FROM Tada
  UNION ALL
  SELECT 
      ID,
      CASE
          WHEN CHARINDEX(',',Remainder) = 0
            THEN Remainder
          WHEN CHARINDEX(',',Remainder) > 0
            THEN LEFT(Remainder,CHARINDEX(',',Remainder) - 1)
      END Val,

      CASE
          WHEN CHARINDEX(',',Remainder) > 0
            THEN RIGHT(Remainder,LEN(Remainder) - CHARINDEX(',',Remainder))
          ELSE NULL
      END Remainder

  FROM Vals
  WHERE Remainder IS NOT NULL
)
SELECT ID, Val
FROM Vals

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接