我需要对varchar(20)字段进行以下修改:
例如
'aèàç=.32s df'
必须成为
'aeacsdf'
是否有特殊的存储功能来轻松实现这一目标?
更新:请提供T-SQL而不是CLR解决方案。这是我临时做的解决方法,因为它暂时适合我的需求,无论如何使用更优雅的方法会更好。
CREATE FUNCTION sf_RemoveExtraChars (@NAME nvarchar(50))
RETURNS nvarchar(50)
AS
BEGIN
declare @TempString nvarchar(100)
set @TempString = @NAME
set @TempString = LOWER(@TempString)
set @TempString = replace(@TempString,' ', '')
set @TempString = replace(@TempString,'à', 'a')
set @TempString = replace(@TempString,'è', 'e')
set @TempString = replace(@TempString,'é', 'e')
set @TempString = replace(@TempString,'ì', 'i')
set @TempString = replace(@TempString,'ò', 'o')
set @TempString = replace(@TempString,'ù', 'u')
set @TempString = replace(@TempString,'ç', 'c')
set @TempString = replace(@TempString,'''', '')
set @TempString = replace(@TempString,'`', '')
set @TempString = replace(@TempString,'-', '')
return @TempString
END
GO
答案 0 :(得分:96)
实现这一目标的最佳方式非常简单有效:
SELECT 'àéêöhello!' Collate SQL_Latin1_General_CP1253_CI_AI
输出'aeeohello!'
字符串不能是unicode。如果你有一个nvarchar,只需在使用整理之前将其强制转换为varchar。
这是一个满足OP需求的功能:
create function [dbo].[RemoveExtraChars] ( @p_OriginalString varchar(50) )
returns varchar(50) as
begin
declare @i int = 1; -- must start from 1, as SubString is 1-based
declare @OriginalString varchar(100) = @p_OriginalString Collate SQL_Latin1_General_CP1253_CI_AI;
declare @ModifiedString varchar(100) = '';
while @i <= Len(@OriginalString)
begin
if SubString(@OriginalString, @i, 1) like '[a-Z]'
begin
set @ModifiedString = @ModifiedString + SubString(@OriginalString, @i, 1);
end
set @i = @i + 1;
end
return @ModifiedString
end
然后,命令:
select dbo.RemoveExtraChars('aèàç=.32s df')
输出
aeacsdf
答案 1 :(得分:15)
您要查找的是从单个字符中删除Diacritics的内容。我担心你的解决方案几乎和你能得到的一样好,至少对于纯SQL来说。但是dotNet / CLR确实提供了a simple method来做到这一点。抱歉,我知道您想要避免使用其他CLR解决方案,但Microsoft SQL Server不提供与此类似的T-SQL。
如果您很幸运,您在数据库中设置collation为“SQL_Latin1_General_CP1_CI_AS”或以“SQL_Latin1_General”开头的任何变体。这相当于Windows-1252,非常好documented。通过查看字符并使用SQL CASE语句映射等效字符,您将能够将每个字符“翻译”为英语等效字符。
但我确实对您的代码进行了一次快速更正。您将要在变量和参数中使用varchar。它会产生额外的开销来回执行数据类型转换,并且有可能将仅作为unicode存在的unicode字符引入混合。此外,可以在Bruce Schneier的博客上找到与您的情况相关的安全相关原因。
更新有关变音符号和Windows国际化的一些重要信息可以在Michael S Kaplan的博客上找到。
答案 2 :(得分:6)
SELECT 'áéíóú' COLLATE Cyrillic_General_CI_AI
这将取代所有重音字符......
结果:aeiou
希望这对你有帮助!
答案 3 :(得分:5)
首先让我澄清一下:你展示的重音字符实际上并不是Unicode(正如一个答案所暗示的);这些是8位ASCII字符。要记住的一件事是:你看到像è和à这样的字符只是因为这是你的代码页(你的操作系统和/或SQL Server使用的代码页[我不确定哪一个])显示它们的方式。在不同的代码页中,这些字符将由完全不同的符号表示(例如,如果您使用西里尔语或土耳其语代码页)。
无论如何,假设您想要使用与默认代码页最接近的美国/拉丁字符替换这些8位字符[我假设这些字符来自拉丁字符集的某些变体]。这就是我遇到类似问题的方法(免责声明:这不是一个非常优雅的解决方案,但当时我想不出更好的事情):
创建UDF以将8位ASCII字符转换为7位可打印ASCII等效字符,例如:
CREATE FUNCTION dbo.fnCharToAscii
(
@Char AS VARCHAR
)
RETURNS
VARCHAR
AS
BEGIN
IF (@Char IS NULL)
RETURN ''
-- Process control and DEL chars.
IF (ASCII(@Char) < 32) OR (ASCII(@Char) = 127)
RETURN ''
-- Return printable 7-bit ASCII chars as is.
-- UPDATE TO DELETE NON-ALPHA CHARS.
IF (ASCII(@Char) >= 32) AND (ASCII(@Char) < 127)
RETURN @Char
-- Process 8-bit ASCII chars.
RETURN
CASE ASCII(@Char)
WHEN 128 THEN 'E'
WHEN 129 THEN '?'
WHEN 130 THEN ','
WHEN 131 THEN 'f'
WHEN 132 THEN ','
WHEN 133 THEN '.'
WHEN 134 THEN '+'
WHEN 135 THEN '+'
WHEN 136 THEN '^'
WHEN 137 THEN '%'
WHEN 138 THEN 'S'
WHEN 139 THEN '<'
WHEN 140 THEN 'C'
WHEN 141 THEN '?'
WHEN 142 THEN 'Z'
WHEN 143 THEN '?'
WHEN 144 THEN '?'
WHEN 145 THEN ''''
WHEN 146 THEN ''''
WHEN 147 THEN '"'
WHEN 148 THEN '"'
WHEN 149 THEN '-'
WHEN 150 THEN '-'
WHEN 151 THEN '-'
WHEN 152 THEN '~'
WHEN 153 THEN '?'
WHEN 154 THEN 's'
WHEN 155 THEN '>'
WHEN 156 THEN 'o'
WHEN 157 THEN '?'
WHEN 158 THEN 'z'
WHEN 159 THEN 'Y'
WHEN 160 THEN ' '
WHEN 161 THEN 'i'
WHEN 162 THEN 'c'
WHEN 163 THEN 'L'
WHEN 164 THEN '?'
WHEN 165 THEN 'Y'
WHEN 166 THEN '|'
WHEN 167 THEN '$'
WHEN 168 THEN '^'
WHEN 169 THEN 'c'
WHEN 170 THEN 'a'
WHEN 171 THEN '<'
WHEN 172 THEN '-'
WHEN 173 THEN '-'
WHEN 174 THEN 'R'
WHEN 175 THEN '-'
WHEN 176 THEN 'o'
WHEN 177 THEN '+'
WHEN 178 THEN '2'
WHEN 179 THEN '3'
WHEN 180 THEN ''''
WHEN 181 THEN 'm'
WHEN 182 THEN 'P'
WHEN 183 THEN '-'
WHEN 184 THEN ','
WHEN 185 THEN '1'
WHEN 186 THEN '0'
WHEN 187 THEN '>'
WHEN 188 THEN '?'
WHEN 189 THEN '?'
WHEN 190 THEN '?'
WHEN 191 THEN '?'
WHEN 192 THEN 'A'
WHEN 193 THEN 'A'
WHEN 194 THEN 'A'
WHEN 195 THEN 'A'
WHEN 196 THEN 'A'
WHEN 197 THEN 'A'
WHEN 198 THEN 'A'
WHEN 199 THEN 'C'
WHEN 200 THEN 'E'
WHEN 201 THEN 'E'
WHEN 202 THEN 'E'
WHEN 203 THEN 'E'
WHEN 204 THEN 'I'
WHEN 205 THEN 'I'
WHEN 206 THEN 'I'
WHEN 207 THEN 'I'
WHEN 208 THEN 'D'
WHEN 209 THEN 'N'
WHEN 210 THEN 'O'
WHEN 211 THEN 'O'
WHEN 212 THEN 'O'
WHEN 213 THEN 'O'
WHEN 214 THEN 'O'
WHEN 215 THEN 'x'
WHEN 216 THEN 'O'
WHEN 217 THEN 'U'
WHEN 218 THEN 'U'
WHEN 219 THEN 'U'
WHEN 220 THEN 'U'
WHEN 221 THEN 'Y'
WHEN 222 THEN 'b'
WHEN 223 THEN 'B'
WHEN 224 THEN 'a'
WHEN 225 THEN 'a'
WHEN 226 THEN 'a'
WHEN 227 THEN 'a'
WHEN 228 THEN 'a'
WHEN 229 THEN 'a'
WHEN 230 THEN 'a'
WHEN 231 THEN 'c'
WHEN 232 THEN 'e'
WHEN 233 THEN 'e'
WHEN 234 THEN 'e'
WHEN 235 THEN 'e'
WHEN 236 THEN 'i'
WHEN 237 THEN 'i'
WHEN 238 THEN 'i'
WHEN 239 THEN 'i'
WHEN 240 THEN 'o'
WHEN 241 THEN 'n'
WHEN 242 THEN 'o'
WHEN 243 THEN 'o'
WHEN 244 THEN 'o'
WHEN 245 THEN 'o'
WHEN 246 THEN 'o'
WHEN 247 THEN '-'
WHEN 248 THEN 'o'
WHEN 249 THEN 'u'
WHEN 250 THEN 'u'
WHEN 251 THEN 'u'
WHEN 252 THEN 'u'
WHEN 253 THEN 'y'
WHEN 254 THEN 'b'
WHEN 255 THEN 'y'
END
RETURN ''
END
上面的代码是通用的,因此您可以调整字符映射以删除所有非字母字符,例如您可以在匹配可打印的7位ASCII字符中使用这样的代码(这假设不区分大小写的排序规则):
IF @Char NOT LIKE '[a-z]' RETURN ''
要查看8位ASCII符号的字符映射是否正常,请运行以下代码:
DECLARE @I INT
DECLARE @Msg VARCHAR(32)
SET @I = 128
WHILE @I < 256
BEGIN
SELECT @Msg = CAST(@I AS VARCHAR) +
': ' +
CHAR(@I) +
'=' +
dbo.fnCharToAscii(CHAR(@I))
PRINT @Msg
SET @I = @I + 1
END
现在您可以创建一个UDF来处理字符串:
CREATE FUNCTION dbo.fnStringToAscii
(
@Value AS VARCHAR(8000)
)
RETURNS
VARCHAR(8000)
AS
BEGIN
IF (@Value IS NULL OR DATALENGTH(@Value) = 0)
RETURN ''
DECLARE @Index INT
DECLARE @Result VARCHAR(8000)
SET @Result = ''
SET @Index = 1
WHILE (@Index <= DATALENGTH(@Value))
BEGIN
SET @Result = @Result + dbo.fnCharToAscii(SUBSTRING(@Value, @Index, 1))
SET @Index = @Index + 1
END
RETURN @Result
END
GO
答案 4 :(得分:4)
您可以使用带有重音不敏感排序规则的REPLACE
子句来避免硬编码COLLATE
语句,以将重音字母字符与非字母字符进行比较:
DECLARE
@s1 NVARCHAR(200),
@s2 NVARCHAR(200)
SET @s1 = N'aèàç=.32s df'
SET @s2 = N''
SELECT @s2 = @s2 + no_accent
FROM (
SELECT
SUBSTRING(@s1, number, 1) AS accent,
number
FROM master.dbo.spt_values
WHERE TYPE = 'P'
AND number BETWEEN 1 AND LEN(@s1)
) s1
INNER JOIN (
SELECT NCHAR(number) AS no_accent
FROM master.dbo.spt_values
WHERE type = 'P'
AND (number BETWEEN 65 AND 90 OR number BETWEEN 97 AND 122)
) s2
ON s1.accent COLLATE LATIN1_GENERAL_CS_AI = s2.no_accent
ORDER BY number
SELECT @s1
SELECT @s2
/*
aèàç=.32s df
aeacsdf
*/
答案 5 :(得分:2)
AFAIK,没有“看起来相似”的unicode / UTF-X字符的直接映射。除非某人有更酷的东西,否则我建议采用蛮力方法,这样你就可以在那之前完成你的工作。
听起来你需要做2次传球。第一步是先替换看起来相似的字母,然后再删除所有剩余的非英文字母。
本文可以帮助您创建用户定义的函数,以便您可以使用正则表达式而不是几十个REPLACE调用:http://msdn.microsoft.com/en-us/magazine/cc163473.aspx
这是我在这种情况下使用的字典:
public static Dictionary<char, string> NonEnglishLetterMapping = new Dictionary<char, string>
{
{'a', "áàâãäåāăą"}
//, {'b', ""}
, {'c', "ćĉċč"}
, {'d', "ďđ"}
, {'e', "éëêèēĕėę"}
//, {'f', ""}
, {'g', "ĝğġģ"}
, {'h', "ĥħ"}
, {'i', "ìíîïĩīĭįı"}
, {'j', "ĵ"}
, {'k', "ķĸ"}
, {'l', "ĺļľŀł"}
//, {'m', ""}
, {'n', "ñńņňʼnŋ"}
, {'o', "òóôõöōŏőơ"}
//, {'p', ""}
//, {'q', ""}
, {'r', "ŕŗř"}
, {'s', "śŝşšș"}
, {'t', "ţťŧț"}
, {'u', "ùúûüũūŭůűųư"}
//, {'v', ""}
, {'w', "ŵ"}
//, {'x', ""}
, {'y', "ŷ"}
, {'z', "źżž"}
};
答案 6 :(得分:2)
嗯,这不是更好,但它至少是一个tsql set解决方案
declare @TempString varchar(100)
set @TempString='textàè containing éìòaccentsç''''` and things-'
select @TempString=
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(@TempString,' ', '')
,'à', 'a')
,'è', 'e')
,'é', 'e')
,'ì', 'i')
,'ò', 'o')
,'ù', 'u')
,'ç', 'c')
,'''', '')
,'`', '')
,'-', '')
select @TempString
答案 7 :(得分:1)
在架构中有两个辅助表,您只需使用SELECT
语句即可转换数据。
首先声明一个视图以实现数字表,从1到65536.以下技术归因于Itzik Ben-Gan:
CREATE VIEW Sequence
AS
WITH T1(_) AS (SELECT NULL UNION ALL SELECT NULL),
T2(_) AS (SELECT NULL FROM T1 AS L CROSS JOIN T1 AS R),
T3(_) AS (SELECT NULL FROM T2 AS L CROSS JOIN T2 AS R),
T4(_) AS (SELECT NULL FROM T3 AS L CROSS JOIN T3 AS R),
T5(_) AS (SELECT NULL FROM T4 AS L CROSS JOIN T4 AS R)
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS Number
FROM T5;
接下来,声明具有变音符号的字符与其无关紧要的等价物之间的映射。此示例数据不是完整映射,但作为示例:
CREATE TABLE UndiacriticMap (
DiacriticCharacter CHAR(1) NOT NULL PRIMARY KEY,
UndiacriticCharacter CHAR(1) NOT NULL
);
INSERT INTO UndiacriticMap (
DiacriticCharacter,
UndiacriticCharacter
)
VALUES
('à', 'a'),
('è', 'e'),
('é', 'e'),
('ì', 'i'),
('ò', 'o'),
('ç', 'c');
最后声明一个包含测试数据的列的表。数据来自问题,来自DForck42's answer:
CREATE TABLE TestData (
ID INT NOT NULL PRIMARY KEY,
String VARCHAR(50) NOT NULL
);
INSERT INTO TestData (
ID,
String
)
VALUES
(1, 'textàè containing éìòaccentsç''''` and things-'),
(2, 'aèàç=.32s df');
在这些对象到位后,以下SELECT
语句以关系方式处理测试数据,除非非关系型黑客将字符连接在一起。 “黑盒XML方法”归于Anith Sen:
WITH CharacterWise (ID, Symbol, Position) AS (
SELECT
ID,
SUBSTRING(TestData.String, Sequence.Number, 1),
Sequence.Number
FROM TestData
INNER JOIN Sequence ON
Sequence.Number <= LEN(TestData.String)
),
Stripped (ID, Symbol, Position) AS (
SELECT
ID,
CASE
WHEN UndiacriticMap.DiacriticCharacter IS NOT NULL
THEN UndiacriticMap.UndiacriticCharacter
ELSE CASE
WHEN CharacterWise.Symbol LIKE '[a-z]' COLLATE Latin1_General_BIN
THEN CharacterWise.Symbol
ELSE ''
END
END,
CharacterWise.Position
FROM CharacterWise
LEFT OUTER JOIN UndiacriticMap ON
UndiacriticMap.DiacriticCharacter = CharacterWise.Symbol
)
SELECT
TestData.ID,
TestData.String,
(
SELECT Stripped.Symbol AS [text()]
FROM Stripped
WHERE TestData.ID = Stripped.ID
ORDER BY Stripped.Position
FOR XML PATH('')
) AS StrippedString
FROM TestData;
查询生成以下结果集:
ID String StrippedString
----------- -------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 textàè containing éìòaccentsç''` and things- textaecontainingeioaccentscandthings
2 aèàç=.32s df aeacsdf
答案 8 :(得分:1)
我知道它并不优雅,但是当整理不起作用且你无法使用函数时,你可以使用这个嵌套的替换来使用最常用的变音符号。我发布这个,所以你不必再自己打字:)
select REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(myfield,'é','e'),'ê','e'),'ë','e'),'è','e'),'É','E'),'È','E'),'Ê','E'),'Ë','E'),'ð','D'),'Ð','D'),'â','a'),'à','a'),'á','a'),'ã','a'),'æ','a'),'à','a'),'å','a'),'Å','A'),'À','A'),'Á','A'),'Â','A'),'Ã','A'),'Æ','A'),'ä','a'),'Ä','A'),'ï','i'),'î','i'),'ì','i'),'í','i'),'Ì','I'),'Í','I'),'Î','I'),'Ï','I'),'ô','o'),'ò','o'),'ó','o'),'õ','o'),'ø','o'),'Ò','O'),'Ó','O'),'Ô','O'),'Õ','O'),'Ø','O'),'ö','o'),'Ö','O'),'û','u'),'ù','u'),'ú','u'),'Ù','U'),'Ú','U'),'Û','U'),'Ü','U'),'ü','u'),'ñ','n'),'Ñ','N'),'Ç','C'),'ç','c'),'ý','y'),'ÿ','y'),'Ý','Y'),'þ','T'),'Þ','t'),'ß','ss') from mytable
答案 9 :(得分:1)
我正在为another question写这个答案,但是OP删除了这个问题,就像我去发布它一样...所以我将它发布在这里,因为它是相关的。这不使用WHILE
或多行标量函数(如最受好评的答案中所示),并且我提供了nvarchar
和varchar
解决方案:
nvarchar
:CREATE FUNCTION dbo.RemoveAccents_N (@String nvarchar(4000))
RETURNS table
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (LEN(@String)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3, N N4)
SELECT (SELECT CASE WHEN V.CS LIKE '[A-z]' THEN V.CS ELSE V.YS END
FROM Tally T
CROSS APPLY (VALUES(SUBSTRING(@String,T.I,1), CONVERT(varchar(4000),SUBSTRING(@String,T.I,1)) COLLATE SQL_Latin1_General_CP1253_CI_AI))V(YS,CS)
FOR XML PATH(N''),TYPE).value('.','nvarchar(4000)') AS AccentlessString;
varchar
:CREATE FUNCTION dbo.RemoveAccents (@String varchar(8000))
RETURNS table
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (LEN(@String)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3, N N4)
SELECT (SELECT CASE WHEN V.CS LIKE '[A-z]' THEN V.CS ELSE V.YS END
FROM Tally T
CROSS APPLY (VALUES(SUBSTRING(@String,T.I,1), SUBSTRING(@String,T.I,1) COLLATE SQL_Latin1_General_CP1253_CI_AI))V(YS,CS)
FOR XML PATH(N''),TYPE).value('.','varchar(8000)') AS AccentlessString;
这些函数可以如下调用:
SELECT *
FROM (VALUES(N'Åìèë Öàíêîâ @11 ώЙ⅔♠♪'))V(YourString)
CROSS APPLY dbo.RemoveAccents_N(V.YourString) RA;
答案 10 :(得分:0)
离我只有两美分
select * From XXX
where cast(word as varchar(max)) collate SQL_Latin1_General_CP1253_CI_AI = 'sluiten' collate SQL_Latin1_General_CP1253_CI_AI
答案 11 :(得分:0)
在postgress 10:
create extension unaccent;# as root in Your db, for each db
select unaccent("ąęśłóŻŹŁÓĄĘ");
:)
答案 12 :(得分:-1)
select * from database_name.table_name
where countries LIKE '%é%'
or countries like'%é%'
or countries like'%ê%'
or countries like'%ë%'
or countries like'%è%'
or countries like'%É%'
or countries like'%È%'
or countries like'%Ê%'
or countries like'%Ë%'
or countries like'%ð%'
or countries like'%Ð%'
or countries like'%â%'
or countries like'%à%'
or countries like'%á%'
or countries like'%ã%'
or countries like'%æ%'
or countries like'%à%'
or countries like'%å%'
or countries like'%Å%'
or countries like'%À%'
or countries like'%Á%'
or countries like'%Â%'
or countries like'%Ã%'
or countries like'%Æ%'
or countries like'%ä%'
or countries like'%Ä%'
or countries like'%ï%'
or countries like'%î%'
or countries like'%ì%'
or countries like'%í%'
or countries like'%Ì%'
or countries like'%Í%'
or countries like'%Î%'
or countries like'%Ï%'
or countries like'%ô%'
or countries like'%ò%'
or countries like'%ó%'
or countries like'%õ%'
or countries like'%ø%'
or countries like'%Ò%'
or countries like'%Ó%'
or countries like'%Ô%'
or countries like'%Õ%'
or countries like'%Ø%'
or countries like'%ö%'
or countries like'%Ö%'
or countries like'%û%'
or countries like'%ù%'
or countries like'%ú%'
or countries like'%Ù%'
or countries like'%Ú%'
or countries like'%Û%'
or countries like'%Ü%'
or countries like'%ü%'
or countries like'%ñ%'
or countries like'%Ñ%'
or countries like'%Ç%'
or countries like'%ç%'
or countries like'%ý%'
or countries like'%ÿ%'
or countries like'%Ý%'
or countries like'%þ%'
or countries like'%Þ%'
or countries like'%ß%';