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

有很多不同的方法来处理字符串解析。这只是一种可能的想法:

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'

dbfiddle