我在表的列中有数据。我选择该列的DISTINCT,同时在编写SELECT时也放置LTRIM(RTRIM(col_name))。但是我仍然得到重复的列记录。
我们如何确定它发生的原因以及如何避免它?
我尝试了RTRIM,LTRIM,UPPER功能。仍然没有帮助。
查询:
select distinct LTRIM(RTRIM(serverstatus))
from SQLInventory
输出:
Development
Staging
Test
Pre-Production
UNKNOWN
NULL
Need to be decommissioned
Production
Pre-Production
Decommissioned
Non-Production
Unsupported Edition
答案 0 :(得分:2)
好像在某处有一个Unicode字符。我最初将这些值复制并粘贴为varchar
,然后执行以下操作:
SELECT DISTINCT serverstatus
FROM (VALUES('Development'),
('Staging'),
('Test'),
('Pre-Production'),
('UNKNOWN'),
('NULL'),
('Need to be decommissioned'),
('Production'),
(''),
('Pre-Production'),
('Decommissioned'),
('Non-Production'),
('Unsupported Edition'))V(serverstatus);
有趣的是,这返回了以下值:
Development
Staging
Test
Pre-Production
UNKNOWN
NULL
Need to be decommissioned
Production
Pre-Produc?tion
Decommissioned
Non-Production
Unsupported Edition
请注意,其中一个值为Pre-Produc?tion
,表示c
和t
之间存在一个Unicode字符。
所以,让我们找出它是什么:
SELECT 'Pre-Production', N'Pre-Production',
UNICODE(SUBSTRING(N'Pre-Production',11,1));
UNICODE
函数返回8203,这是一个零宽度的空间。我假设您要删除这些内容,因此您可以执行以下操作来更新数据:
UPDATE SQLInventory
SET serverstatus = REPLACE(serverstatus, NCHAR(8203), N'');
现在,您的第一个查询应该可以按预期工作。
(我还建议您可能需要一个带有外键的状态查询表,以免再次发生这种情况。)
答案 1 :(得分:0)
我一直都在处理这类事情。对于诸如NGrams8K,PatReplace8k和PATINDEX这样的事物,您是最好的朋友。
将您发布的内容放入表变量中,我们可以分析问题:
DECLARE @table TABLE (txtID INT IDENTITY, txt NVARCHAR(100));
INSERT @table (txt)
VALUES ('Development'),('Staging'),('Test'),('Pre-Production'),('UNKNOWN'),(NULL),
('Need to be decommissioned'),('Production'),(''),('Pre-Production'),('Decommissioned'),
('Non-Production'),('Unsupported Edition');
此查询将识别带有A-Z,空格和连字符以外的字符的项目:
SELECT t.txtID, t.txt
FROM @table AS t
WHERE PATINDEX('%[^a-zA-Z -]%',t.txt) > 0;
这将返回:
txtID txt
----------- -------------------------------------------
10 Pre-Production
要确定坏字符,我们可以像这样使用NGrams8k:
SELECT t.txtID, t.txt, ng.position, ng.token -- ,UNICODE(ng.token)
FROM @table AS t
CROSS APPLY dbo.NGrams8K(t.txt,1) AS ng
WHERE PATINDEX('%[^a-zA-Z -]%',ng.token)>0;
哪个返回:
txtID txt position token
------ ----------------- -------------------- ---------
10 Pre-Production 11 ?
PatReplace8K可以非常轻松快捷地清理此类内容。首先请注意此查询:
SELECT OldString = t.txt, p.NewString
FROM @table AS t
CROSS APPLY dbo.patReplace8K(t.txt,'%[^a-zA-Z -]%','') AS p
WHERE PATINDEX('%[^a-zA-Z -]%',t.txt) > 0;
哪个在我的系统上返回:
OldString NewString
------------------ ----------------
Pre-Produc?tion Pre-Production
要解决此问题,您可以像这样使用patreplace8K:
UPDATE t
SET txt = p.newString
FROM @table AS t
CROSS APPLY dbo.patReplace8K(t.txt,'%[^a-zA-Z -]%','') AS p
WHERE PATINDEX('%[^a-zA-Z -]%',t.txt) > 0;