SQL 服务器 - 基于 ASCII 值的 CHARINDEX
SQL Server - CHARINDEX on ASCII values
我在 SQL 服务器 table 上有一个列,该列的值很长且带有换行符。我试图在每个换行符之前找到值。
示例:
--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
表示回车 return 和换行。
首选结果:
现在数据已经清楚了,我正在尝试找到冒号之后和换行符之前的值并将其放入新列中。
所以这是我希望的结果应该是这样的:
我尝试了什么:
这是我当前的 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:" 的子字符串)。对于 Cut
,我得到 8" x 3/
。对于 Additions
,我得到 Brin
("Cover Brine" 的子字符串)。
我做错了什么!!我尝试了多种不同的子串长度组合。我知道这是长度。但是现在我意识到风味代码搞砸后的所有起始位置,我不太确定错误在哪里。
如有任何帮助,我们将不胜感激。
谢谢。
经过大约一周的时间来解决这个问题,并尝试将我的执行想法转移到评论中提到的建议中,我最终找到了解决这个问题的方法。
第 1 步:
我发现操作像 !
这样的特殊字符比换行和换行(Char(10)
和 Char(13)
)更容易。
所以我做的第一件事就是将所有换行符替换为!
。像这样:
REPLACE(REPLACE(columnName, char(10), ''), char(13), '!')
这确保 !
前面总是有一个 space,使其更容易处理。
第 2 步:
我在 SO 上找到了一个答案,它有一个 table-value 函数来拆分字符串。函数名称是 fnSplitString
,它有两个参数:@string nvarchar(MAX)
和 @delimited char(1)
.
ALTER FUNCTION [dbo].[fnSplitString]
(
@string NVARCHAR(MAX),
@delimiter CHAR(1)
)
RETURNS @output TABLE(columnName NVARCHAR(MAX), outValue NVARCHAR(MAX))
BEGIN
DECLARE
@start INT
,@end INT
,@colon INT
SELECT
@start = 1
,@colon = CHARINDEX(@delimiter, @string)
,@end = CHARINDEX(CHAR(33), @string)
WHILE @start < LEN(@string) + 1 BEGIN
IF(SUBSTRING(@string, @colon + 1, 1) = ' ')
BEGIN
INSERT INTO
@output (columnName, outValue)
VALUES
((SUBSTRING(@string, @start, @colon - @start)) ,(SUBSTRING(@string, @colon + 2, @end - @colon - 2)))
SET @start = @end + 1
SET @colon = CHARINDEX(@delimiter, @string, @start)
SET @end = CHARINDEX(CHAR(33), @string, @start)
END
ELSE
BEGIN
INSERT INTO
@output (columnName, outValue)
VALUES
((SUBSTRING(@string, @start, @colon - @start)) ,(SUBSTRING(@string, @colon + 1, @end - @colon - 1)))
SET @start = @end + 1
SET @colon = CHARINDEX(@delimiter, @string, @start)
SET @end = CHARINDEX(CHAR(33), @string, @start)
END
END
RETURN
END
我不得不对该函数进行大量更改,因为该函数最初用于获取分隔符之后直至字符串末尾的值,这非常简单。但是我的必须从分隔符转到 !
,即 char(33)
。
第 3 步:
我编写了一个存储过程来处理所有这些操作。我已经为我的要求准备了一个相当冗长的存储过程,我必须将此函数的结果与 select 语句的结果一起添加到新的 CTE 中,并在最终结果集中使用它。
对于任何好奇的人,在另一个 SO 问题中发现 table 和函数的连接可以像这样完成:
SELECT
table1.columnName1
,function1.columnName2
,function1.columnName3
FROM
tableName1 table1
CROSS APPLY
dbo.functionName1(table1.columnName2, ':') function1
做到了。
我希望这对以后的人有所帮助。
我在 SQL 服务器 table 上有一个列,该列的值很长且带有换行符。我试图在每个换行符之前找到值。
示例:
--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
表示回车 return 和换行。
首选结果:
现在数据已经清楚了,我正在尝试找到冒号之后和换行符之前的值并将其放入新列中。
所以这是我希望的结果应该是这样的:
我尝试了什么:
这是我当前的 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:" 的子字符串)。对于 Cut
,我得到 8" x 3/
。对于 Additions
,我得到 Brin
("Cover Brine" 的子字符串)。
我做错了什么!!我尝试了多种不同的子串长度组合。我知道这是长度。但是现在我意识到风味代码搞砸后的所有起始位置,我不太确定错误在哪里。
如有任何帮助,我们将不胜感激。
谢谢。
经过大约一周的时间来解决这个问题,并尝试将我的执行想法转移到评论中提到的建议中,我最终找到了解决这个问题的方法。
第 1 步:
我发现操作像 !
这样的特殊字符比换行和换行(Char(10)
和 Char(13)
)更容易。
所以我做的第一件事就是将所有换行符替换为!
。像这样:
REPLACE(REPLACE(columnName, char(10), ''), char(13), '!')
这确保 !
前面总是有一个 space,使其更容易处理。
第 2 步:
我在 SO 上找到了一个答案,它有一个 table-value 函数来拆分字符串。函数名称是 fnSplitString
,它有两个参数:@string nvarchar(MAX)
和 @delimited char(1)
.
ALTER FUNCTION [dbo].[fnSplitString]
(
@string NVARCHAR(MAX),
@delimiter CHAR(1)
)
RETURNS @output TABLE(columnName NVARCHAR(MAX), outValue NVARCHAR(MAX))
BEGIN
DECLARE
@start INT
,@end INT
,@colon INT
SELECT
@start = 1
,@colon = CHARINDEX(@delimiter, @string)
,@end = CHARINDEX(CHAR(33), @string)
WHILE @start < LEN(@string) + 1 BEGIN
IF(SUBSTRING(@string, @colon + 1, 1) = ' ')
BEGIN
INSERT INTO
@output (columnName, outValue)
VALUES
((SUBSTRING(@string, @start, @colon - @start)) ,(SUBSTRING(@string, @colon + 2, @end - @colon - 2)))
SET @start = @end + 1
SET @colon = CHARINDEX(@delimiter, @string, @start)
SET @end = CHARINDEX(CHAR(33), @string, @start)
END
ELSE
BEGIN
INSERT INTO
@output (columnName, outValue)
VALUES
((SUBSTRING(@string, @start, @colon - @start)) ,(SUBSTRING(@string, @colon + 1, @end - @colon - 1)))
SET @start = @end + 1
SET @colon = CHARINDEX(@delimiter, @string, @start)
SET @end = CHARINDEX(CHAR(33), @string, @start)
END
END
RETURN
END
我不得不对该函数进行大量更改,因为该函数最初用于获取分隔符之后直至字符串末尾的值,这非常简单。但是我的必须从分隔符转到 !
,即 char(33)
。
第 3 步:
我编写了一个存储过程来处理所有这些操作。我已经为我的要求准备了一个相当冗长的存储过程,我必须将此函数的结果与 select 语句的结果一起添加到新的 CTE 中,并在最终结果集中使用它。
对于任何好奇的人,在另一个 SO 问题中发现 table 和函数的连接可以像这样完成:
SELECT
table1.columnName1
,function1.columnName2
,function1.columnName3
FROM
tableName1 table1
CROSS APPLY
dbo.functionName1(table1.columnName2, ':') function1
做到了。
我希望这对以后的人有所帮助。