SQL Server 2012 字符串函数
SQL Server 2012 string functions
我有一个长度可以变化的字段,格式为 CxxRyyy,其中 x 和 y 是数字。我想选择 xx 和 yyy。例如,如果字段值为 C1R12,那么我想得到 1 和 12。如果我使用 substring 和 charindex,那么我必须使用长度,但我想使用像
这样的位置
SUBSTRING(WPLocationNew, CHARINDEX('C',WPLocationNew,1)+1, CHARINDEX('R',WPLocationNew,1)-1)
或
SUBSTRING(WPLocationNew, CHARINDEX('C',WPLocationNew,1)+1, LEN(WPLocationNew) - CHARINDEX('R',WPLocationNew,1))
得到 x,但我知道那行不通。我觉得有一个相当简单的解决方案,但我还没有想出它。有什么建议
您似乎正在尝试解析 Excel 单元格引用。这些都是可预见的结构,否则我不会建议像这样令人尴尬的黑客攻击。
基本上,利用 SQL 中的 try_cast 在将字符串转换为数字时忽略空格这一事实。
declare @val as varchar(20) = 'C1R12'
declare @newval as varchar(20)
declare @c as smallint
declare @r as smallint
--replace the C with 5 spaces
set @newval = replace(@val,'C',' ')
--replace the R with 5 spaces
set @newval = replace(@newval,'R',' ')
--take a look at the intermediate result, which is ' 1 14'
select @newval
set @c = try_cast(left(@newval,11) as smallint)
set @r = try_cast(right(@newval,6) as smallint)
--take a look at the results... two smallint, 1 and 14
select @c, @r
每个元素都可以在一行中完成(一行代表列,一行代表行),但我希望您能够理解发生了什么,所以这个例子单独完成了这些步骤。
如果这些是单元格引用并且将始终采用 C{1-5 digits}R{1-5 digits}
形式,您可以这样做:
DECLARE @t TABLE(Original varchar(32));
INSERT @t(Original) VALUES ('C14R4535'),('C1R12'),('C57R123');
;WITH src AS
(
SELECT Original, c = REPLACE(REPLACE(Original,'C',''),'R','.')
FROM @t
)
SELECT Original, C = PARSENAME(c,2), R = PARSENAME(c,1)
FROM src;
输出
Original
C
R
C14R4535
14
4535
C1R12
1
12
C57R123
57
123
如果需要防范其他格式,可以添加
FROM @t WHERE Original LIKE 'C%[0-9]%R%[0-9]%'
AND PATINDEX('%[^C^R^0-9]%', Original) = 0
- 已更新db<>fiddle
有很多不同的方法来处理字符串解析。这只是一种可能的想法:
declare @s varchar(10) = 'C01R002';
select
rtrim( left(replace(stuff(@s, 1, 1, ''), 'R', ' '), 10)) as c,
ltrim(right(replace(substring(@s, 2, 10), 'R', ' '), 10)) as r
把'C'去掉,然后把'R'换成足够的空格,这样左右两边就可以用固定的长度提取出来,然后很容易修剪回来。
上面使用的 stuff()
和 substring()
只是完成完全相同事情的不同方式。这里的一个优点是它确实使用了相当可移植的字符串函数,并且可以想象这会更快一些。这也是在线完成的,没有多个步骤。
还有另一种方法:
declare @val as varchar(20) = 'C12R345'
declare @c as varchar(5)
declare @r as varchar(5)
set @c = SUBSTRING(@val, patindex('C%', @val)+1,(patindex('%R%', @val)-1)-patindex('C%', @val) )
set @r = SUBSTRING(@val, patindex('%R%', @val)+1, LEN(@val) -patindex('%R%', @val))
select cast(@c as int) as 'C', cast(@r as int) as 'R'
我有一个长度可以变化的字段,格式为 CxxRyyy,其中 x 和 y 是数字。我想选择 xx 和 yyy。例如,如果字段值为 C1R12,那么我想得到 1 和 12。如果我使用 substring 和 charindex,那么我必须使用长度,但我想使用像
这样的位置SUBSTRING(WPLocationNew, CHARINDEX('C',WPLocationNew,1)+1, CHARINDEX('R',WPLocationNew,1)-1)
或
SUBSTRING(WPLocationNew, CHARINDEX('C',WPLocationNew,1)+1, LEN(WPLocationNew) - CHARINDEX('R',WPLocationNew,1))
得到 x,但我知道那行不通。我觉得有一个相当简单的解决方案,但我还没有想出它。有什么建议
您似乎正在尝试解析 Excel 单元格引用。这些都是可预见的结构,否则我不会建议像这样令人尴尬的黑客攻击。
基本上,利用 SQL 中的 try_cast 在将字符串转换为数字时忽略空格这一事实。
declare @val as varchar(20) = 'C1R12'
declare @newval as varchar(20)
declare @c as smallint
declare @r as smallint
--replace the C with 5 spaces
set @newval = replace(@val,'C',' ')
--replace the R with 5 spaces
set @newval = replace(@newval,'R',' ')
--take a look at the intermediate result, which is ' 1 14'
select @newval
set @c = try_cast(left(@newval,11) as smallint)
set @r = try_cast(right(@newval,6) as smallint)
--take a look at the results... two smallint, 1 and 14
select @c, @r
每个元素都可以在一行中完成(一行代表列,一行代表行),但我希望您能够理解发生了什么,所以这个例子单独完成了这些步骤。
如果这些是单元格引用并且将始终采用 C{1-5 digits}R{1-5 digits}
形式,您可以这样做:
DECLARE @t TABLE(Original varchar(32));
INSERT @t(Original) VALUES ('C14R4535'),('C1R12'),('C57R123');
;WITH src AS
(
SELECT Original, c = REPLACE(REPLACE(Original,'C',''),'R','.')
FROM @t
)
SELECT Original, C = PARSENAME(c,2), R = PARSENAME(c,1)
FROM src;
输出
Original C R C14R4535 14 4535 C1R12 1 12 C57R123 57 123
如果需要防范其他格式,可以添加
FROM @t WHERE Original LIKE 'C%[0-9]%R%[0-9]%'
AND PATINDEX('%[^C^R^0-9]%', Original) = 0
- 已更新db<>fiddle
有很多不同的方法来处理字符串解析。这只是一种可能的想法:
declare @s varchar(10) = 'C01R002';
select
rtrim( left(replace(stuff(@s, 1, 1, ''), 'R', ' '), 10)) as c,
ltrim(right(replace(substring(@s, 2, 10), 'R', ' '), 10)) as r
把'C'去掉,然后把'R'换成足够的空格,这样左右两边就可以用固定的长度提取出来,然后很容易修剪回来。
上面使用的stuff()
和 substring()
只是完成完全相同事情的不同方式。这里的一个优点是它确实使用了相当可移植的字符串函数,并且可以想象这会更快一些。这也是在线完成的,没有多个步骤。
还有另一种方法:
declare @val as varchar(20) = 'C12R345'
declare @c as varchar(5)
declare @r as varchar(5)
set @c = SUBSTRING(@val, patindex('C%', @val)+1,(patindex('%R%', @val)-1)-patindex('C%', @val) )
set @r = SUBSTRING(@val, patindex('%R%', @val)+1, LEN(@val) -patindex('%R%', @val))
select cast(@c as int) as 'C', cast(@r as int) as 'R'