【发布时间】:2018-05-29 18:32:52
【问题描述】:
我在 SQL Server 表中有一个列,该列的值很长,带有换行符。我试图在每个换行符之前找到值。
示例:
--Column name: ItemDescription
Case Qty: 12
Weight: 8 oz.
Flavor code: PB
Size: STOCK
Cut: 1/8" x 1/8" x 3/16"
Additions: Bells
Cover Brine #: P1
Kosher Cert: OU
Organic Cert:
这正是我在结果中复制单元格并粘贴时得到的结果。所以我将此字段转换为VARBINARY 并查看ASCII 代码在此处。这是一个值的 ASCII 解释的一部分:
43 61 73 65 20 51 74 79 3A 20 31 32 0D0A 57 65 69 67 68 74 3A 20 38 20 6F 7A 2E 0D0A 46
0D0A 表示回车和换行。
首选结果:
现在数据已经清楚了,我正在尝试在冒号之后和换行符之前找到值并将其放入新列中。
这就是我想要的结果:
我的尝试:
这是我当前执行此操作的 SQL 查询:
DECLARE @firstLine int
DECLARE @secondLine int
DECLARE @thirdLine int
DECLARE @fourthLine int
DECLARE @fifthLine int
DECLARE @sixthLine int
DECLARE @seventhLine int
DECLARE @eighthLine int
DECLARE @firstColon int
DECLARE @secondColon int
DECLARE @thirdColon int
DECLARE @fourthColon int
DECLARE @fifthColon int
DECLARE @sixthColon int
DECLARE @seventhColon int
DECLARE @eighthColon int
DECLARE @ninethColon int
DECLARE @itemDesc varchar(MAX)
SELECT
@itemDesc = ItemDescription
,@firstLine = CHARINDEX(CHAR(13), ItemDescription, 1)
,@secondLine = CHARINDEX(CHAR(13), ItemDescription, @firstLine + 1)
,@thirdLine = CHARINDEX(CHAR(13), ItemDescription, @secondLine + 1)
,@fourthLine = CHARINDEX(CHAR(13), ItemDescription, @thirdLine + 1)
,@fifthLine = CHARINDEX(CHAR(13), ItemDescription, @fourthLine+ 1)
,@sixthLine = CHARINDEX(CHAR(13), ItemDescription, @fifthLine + 1)
,@seventhLine = CHARINDEX(CHAR(13), ItemDescription, @sixthLine + 1)
,@eighthLine = CHARINDEX(CHAR(13), ItemDescription, @seventhLine + 1)
,@firstColon = CHARINDEX(CHAR(58), ItemDescription, 1)--aaa
,@secondColon = CHARINDEX(CHAR(58), ItemDescription, @firstLine + 1)
,@thirdColon = CHARINDEX(CHAR(58), ItemDescription, @secondLine + 1)
,@fourthColon = CHARINDEX(CHAR(58), ItemDescription, @thirdLine + 1)
,@fifthColon = CHARINDEX(CHAR(58), ItemDescription, @fourthLine + 1)
,@sixthColon = CHARINDEX(CHAR(58), ItemDescription, @fifthLine + 1)
,@seventhColon = CHARINDEX(CHAR(58), ItemDescription, @sixthLine + 1)
,@eighthColon = CHARINDEX(CHAR(58), ItemDescription, @seventhLine + 1)
,@ninethColon = CHARINDEX(CHAR(58), ItemDescription, @eighthLine + 1)
FROM TableName
SELECT
ItemDescription
,CONVERT(VarBInary, itemDescription)
,LTRIM(SUBSTRING(ItemDescription, @firstColon + 2, @firstLine - (@firstColon - 1))) as caseQty --1
,LTRIM(SUBSTRING(ItemDescription, @secondColon + 2, @secondLine - (@secondColon - 1))) as caseQty --2
,LTRIM(SUBSTRING(ItemDescription, @thirdColon + 2, @thirdLine - (@thirdColon - 1))) as FlavorCode
,LTRIM(SUBSTRING(ItemDescription, @fourthColon + 2, @fourthLine - (@fourthColon - 1))) as Size
,LTRIM(SUBSTRING(ItemDescription, @fifthColon + 2, @fifthLine - (@fifthColon - 1))) as Cut
,LTRIM(SUBSTRING(ItemDescription, @sixthColon + 2, @sixthLine - (@sixthColon - 1))) as Additions
,LTRIM(SUBSTRING(ItemDescription, @eighthColon + 2, @eighthLine- (@eighthColon - 1))) as Brine
FROM
TableName
问题:
由于某种原因,SUBSTRING 没有得到正确的子字符串!我正确地得到了Qty 和Weight。但是如果大小是RELISHSTOCK,我得到RELISHSTOC。对于FlavorCode,我得到ut:(“剪切:”的子字符串)。对于Cut,我得到8" x 3/。对于Additions,我得到Brin(“Cover Brine”的子字符串)。
我做错了什么!!我尝试了多种不同的子字符串长度组合。我知道事实上它是长度。但是现在我意识到风味代码搞砸后的所有起始位置,我不太确定错误在哪里。
任何帮助将不胜感激。
谢谢。
【问题讨论】:
-
T-SQL 不适合字符串操作,更不用说解析了。如果您想存储复杂的数据,请将它们存储为 XML 或 Json。在加载/插入数据时,使用 C# 之类的语言解析数据会更容易很多
-
@PanagiotisKanavos 看,就是这样。这张表中的数据很简单,只用 T-SQL 就可以搞定。我在 XML 方面很糟糕,甚至不想为自己打开那罐蠕虫。但这些数据不会去任何地方。它只是去一个 SSRS 报告。所以我想我可以让它像这样工作。
-
另外,如果你已经知道数据会有特定的字段,为什么不首先为它创建一个表呢?在 C# 中使用正则表达式解析字符串非常容易。提取键/值对并将它们作为字段值插入到表中
-
问题是您的数据违反了 1NF,将多条数据存储在一个元组中。通过在单个元组中存储多行多个数据点,您的更进一步。您有一个 EAV 类型模式存储在单行中。这是处理sql的噩梦。
-
一种可能的解决方法(不是解决方案,真正的解决方案是改变加载数据的方式并直接将其插入到 中)是将其转换为 JSON,然后使用 SQL Server 的 JSON 函数提取属性.例如,用
','替换每个换行符,用' : '替换每个:并用'{'和'}包装所有内容,这会使它看起来像JSON。然后您可以使用JSON_QUERY 来读取属性。不过,这将是 slow。修复数据
标签: sql-server select substring ascii charindex