使用SQL Server 2016,我需要以某种方式清除空白并实现INITCAP。
空白清除器很简单。我在替换INITCAP时遇到了问题。
Initcap equivalent in mssql的公认答案是错误的,正如第一条评论中所指出的。
我的数据包含一行中有多个空格和特殊字符(&、%等)的值。stuff()
:在SQL Server 2016中,string_split
没有证明序数值的选项,也不保证结果以任何特定顺序返回。因此,我需要编写代码以确保值以正确顺序从split_string
返回。convert(xml,...)
:解码大多数XML编码值。convert(varchar(max),...)
:...因为在需要SELECT DISTINCT
时无法使用XML
SQL Fiddle
with T as (
select *
from (
values ('Minesota Mining and Manufacturing')
, ('Minesota Mining & Manufacturing ')
, (' tillamook')
, ('MUTUAL OF OMAHA')
, (' ')
) q(s)
),
scrubbed as (
select T.s as InitialValue
, CASE
WHEN LEN(RTRIM(T.s)) > 0
THEN LTRIM(RTRIM(T.s))
END as s
from T
)
select distinct s.InitialValue
, stuff(
(
SELECT ' ' + t2.word
from (
select str.value
, upper(substring(str.value, 1, 1)) +
case when len(str.value) > 1 then lower(substring(str.value, 2, len(str.value) - 1)) else '' end as word
, charindex(' ' + str.value + ' ', ' ' + s.s + ' ') as idx
from string_split(s.s, ' ') str
) t2
order by t2.idx
FOR XML PATH('')
),
1,
1,
''
) as INITCAP_xml
, convert(
varchar(max),
convert(
xml,
stuff(
(
SELECT ' ' + t2.word
from (
select str.value
, upper(substring(str.value, 1, 1)) +
case when len(str.value) > 1 then lower(substring(str.value, 2, len(str.value) - 1)) else '' end as word
, charindex(' ' + str.value + ' ', ' ' + s.s + ' ') as idx
from string_split(s.s, ' ') str
) t2
order by t2.idx
FOR XML PATH('')
),
1,
1,
''
)
)
) as INITCAP_decoded
from scrubbed s
在输出中可以看到,使用FOR XML
会导致一些字符被编码(如[space]= $#x20;
和&= &
),通过转换为XML数据类型,这些字符中的一些被解码,但一些字符(如&
)仍然是编码的。
| 初始值|初始化CAP_尝试1|初始化CAP_xml|INITCAP_已解码|
| - ------|- ------|- ------|- ------|
| Minesota Mining and Manufacturing
|x1米11米1x|Minesota Mining And Manufacturing
|Minesota Mining And Manufacturing
|
| Minesota Mining & Manufacturing
|Minesota Mining & Manufacturing
|Minesota Mining & Manufacturing
|Minesota Mining & Manufacturing
|
| tillamook
|Tillamook
|x1米20英寸1x|Tillamook
|
| MUTUAL OF OMAHA
|Mutual Of Omaha
|Mutual Of Omaha
|Mutual Of Omaha
|
|
|* 无效 | 无效 | 无效 *|REPLACE(s, '&', '&')
似乎不是一个合理的选择,因为我不知道随着时间的推移会遇到什么其他值。有没有一种好的、通用的方法来处理将由FOR XML
编码的字符?
在视图中(因此,不使用用户定义的函数或存储过程),是否有更好的方法在SQL Server中实现INITCAP
?
3条答案
按热度按时间nwlls2ji1#
如果对SVF感兴趣,这里有一个缩小的版本,它允许定制和边缘事件。例如,你会得到
Phd
而不是PhD
... MacDonald,O'Neil这是一个大大缩小的版本。我的规则/例外在一个通用的Map表中。
结果
enxuqcxy2#
请尝试以下解决方案。
它使用SQL Server XML、XQuery及其FLWOR表达式。
值得注意的要点:
cast as xs:token?
负责空格,即:| 代币|擦洗过的|结果|
| - ------|- ------|- ------|
| 矿业和制造|矿业和制造|Minesota采矿和制造业|
| Minesota采矿和制造|Minesota采矿和制造|Minesota采矿和制造|
| 蒂拉穆克|蒂拉穆克|蒂拉穆克|
| 奥马哈互助会|奥马哈互助会|奥马哈互助银行|
| 零|||
kmpatx3s3#
你犯了一个典型的SQL Server XML错误,不能只使用PATH('')。你必须做一些复杂的PATH(''),TYPE).value('.','NVARCHAR(MAX)')来获得正确的编码字符。
以下是您的修复版本: