2009-03-26 8 views
31

मेरे पास दो हजार पंक्तियों वाली एक टेबल है। विवरण और सारांश फ़ील्ड NTEXT हैं, और कभी-कभी उनमें गैर-ASCII वर्ण होते हैं। मैं गैर ASCII वर्णों वाली सभी पंक्तियों का पता कैसे लगा सकता हूं?SQL सर्वर 2005 तालिका में NTEXT फ़ील्ड में यूनिकोड/गैर-ASCII वर्ण कैसे प्राप्त कर सकते हैं?

उत्तर

15

पहले उन सभी पात्रों के साथ एक स्ट्रिंग बनाएं जिसमें आप रुचि नहीं रखते हैं (उदाहरण 0x20 - 0x7F रेंज, या नियंत्रण वर्णों के बिना 7 बिट्स का उपयोग करता है।) प्रत्येक वर्ण से बच निकला है, भागने के खंड में उपयोग के लिए बाद में।

-- Start with tab, line feed, carriage return 
declare @str varchar(1024) 
set @str = '|' + char(9) + '|' + char(10) + '|' + char(13) 

-- Add all normal ASCII characters (32 -> 127) 
declare @i int 
set @i = 32 
while @i <= 127 
    begin 
    -- Uses | to escape, could be any character 
    set @str = @str + '|' + char(@i) 
    set @i = @i + 1 
    end 

अगला स्निपेट किसी भी चरित्र की खोज करता है जो सूची में नहीं है। % 0 या अधिक वर्णों से मेल खाता है। [] [] के अंदर वर्णों में से एक से मेल खाता है, उदाहरण के लिए [एबीसी] या तो ए, बी या सी से मेल खाता है।^सूची को अस्वीकार करता है, उदाहरण के लिए [^ एबीसी] किसी भी चीज से मेल खाता है जो ए, बी, या सी नहीं है।

select * 
from yourtable 
where yourfield like '%[^' + @str + ']%' escape '|' 

बचने के चरित्र की आवश्यकता है क्योंकि अन्यथा जैसे पात्रों की खोज करना,% या _ LIKE अभिव्यक्ति को गड़बड़ कर देगा।

आशा है कि यह उपयोगी है, और दूसरे जवाब पर जॉनएफएक्स की टिप्पणी के लिए धन्यवाद।

+0

आप 32 से नीचे पात्रों में से कुछ (या सभी) के साथ-साथ, विशेष रूप से महत्वपूर्ण होगा कैरिज रिटर्न जोड़ सकते हैं (13), रेखा फ़ीड (10), और टैब (9)। –

+0

अच्छा बिंदु जोड़ा गया – Andomar

+1

मुझे आपकी तकनीक को SQL-Server में ऐसा करने का सबसे विश्वसनीय तरीका माना गया है। – cusman

2

यह शायद सबसे अच्छा समाधान नहीं है, लेकिन हो सकता है की तरह एक प्रश्न:

SELECT * 
FROM yourTable 
WHERE yourTable.yourColumn LIKE '%[^0-9a-zA-Z]%' 

कि पूर्ण ASCII सेट कब्जा कुछ के साथ "0-9a-zA-Z" अभिव्यक्ति (या एक सबसेट है कि बदलें अपनी डेटा में शामिल हैं)।

+0

क्या यह सिर्फ उन पंक्तियों से मेल नहीं खाएगा जिनमें कोई ASCII वर्ण शामिल है, केवल ASCII वर्णों का विरोध करते हुए? – Andomar

+0

^अभिव्यक्ति के मोर्चे पर मार्कर का मतलब नहीं है, इसलिए नहीं। यह किसी भी पंक्ति को प्राप्त करेगा जिसमें कम से कम एक वर्ण था जो निर्दिष्ट श्रेणियों में नहीं था। – JohnFx

+0

मैं उस अभिव्यक्ति में पूर्ण एसीआई सेट कैसे रख सकता हूं? यह HTML डेटा है जिसे मैं देख रहा हूं "/><'आदि ... वहां है। – TheSoftwareJedi

0

मेरा पिछला उत्तर यूनिकोड/गैर-यूनिकोड डेटा को भ्रमित कर रहा था। यहां एक समाधान है जो सभी परिस्थितियों के लिए काम करना चाहिए, हालांकि मैं अभी भी कुछ विसंगतियों में चल रहा हूं। ऐसा लगता है कि सुपरस्क्रिप्ट वर्णों के लिए कुछ गैर-ASCII यूनिकोड वर्ण वास्तविक संख्या वर्ण के साथ उलझन में हैं। आप आसपास के लिए पाने के लिए collations के साथ खेल सकते हैं।

उम्मीद है कि आपके पास पहले से ही आपके डेटाबेस में एक संख्या तालिका है (वे बहुत उपयोगी हो सकते हैं), लेकिन अगर मैंने कोड को आंशिक रूप से भरने के लिए कोड भी शामिल किया है।

तुम भी यूनिकोड वर्ण से परे 255.

CREATE TABLE dbo.Numbers 
(
    number INT NOT NULL, 
    CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (number) 
) 
GO 
DECLARE @i INT 

SET @i = 0 

WHILE @i < 1000 
BEGIN 
    INSERT INTO dbo.Numbers (number) VALUES (@i) 

    SET @i = @i + 1 
END 
GO 

SELECT *, 
    T.ID, N.number, N'%' + NCHAR(N.number) + N'%' 
FROM 
    dbo.Numbers N 
INNER JOIN dbo.My_Table T ON 
    T.description LIKE N'%' + NCHAR(N.number) + N'%' OR 
    T.summary LIKE N'%' + NCHAR(N.number) + N'%' 
and t.id = 1 
WHERE 
    N.number BETWEEN 127 AND 255 
ORDER BY 
    T.id, N.number 
GO 
+0

जिस तरह से मैं इसे समझता हूं, ASCII 7 बिट है और वर्कर 8 बिट है। तो वर्कर अभी भी बहुत सारे पात्रों को स्टोर कर सकता है जो एसीआई नहीं हैं, जैसे ä या é। – Andomar

+0

मैं एक ही परिणाम देख रहा हूँ। यह काम नहीं करता है। – TheSoftwareJedi

+1

विस्तारित एएससीआईआई 8 बिट है, जो कुछ लोग "ASCII" कहने का जिक्र कर रहे हैं। मैं पोस्ट को सामान्य ASCII तक सीमित करने के लिए भी संपादित करूंगा। –

-1

जा सकते हैं के बाद से, सांख्यिक श्रेणी के साथ चारों ओर खेलने के लिए आवश्यकता हो सकती है - यह बात करने का एक बहुत, बहुत अक्षम तरीका है, लेकिन के लिए ठीक होना चाहिए छोटी टेबल यह इट्ज़िक बेन-गण के अनुसार संख्याओं की एक सहायक तालिका का उपयोग करता है और बस - बिट 7 सेट वाले अक्षर ढूंढता है।

SELECT * 
FROM yourTable as t 
WHERE EXISTS (SELECT * 
       FROM msdb..Nums as NaturalNumbers 
       WHERE NaturalNumbers.n < LEN(t.string_column) 
         AND ASCII(SUBSTRING(t.string_column, NaturalNumbers.n, 1)) > 127) 
3

तकनीकी तौर पर, मुझे विश्वास है कि एक NCHAR (1) एक वैध ASCII वर्ण है यदि & केवल तभी यूनिकोड (@NChar) < 256 और ASCII (@NChar) = यूनिकोड (@NChar) यह है कि नहीं किया जा सकता वास्तव में आप क्या इरादा है। इसलिए यह एक सही समाधान होगा:

;With cteNumbers as 
(
    Select ROW_NUMBER() Over(Order By c1.object_id) as N 
    From sys.system_columns c1, sys.system_columns c2 
) 
Select Distinct RowID 
From YourTable t 
    Join cteNumbers n ON n <= Len(CAST(TXT As NVarchar(MAX))) 
Where UNICODE(Substring(TXT, n.N, 1)) > 255 
    OR UNICODE(Substring(TXT, n.N, 1)) <> ASCII(Substring(TXT, n.N, 1)) 

यह भी बहुत तेज़ होना चाहिए।

+0

ASCII केवल 127 तक है। इसके अलावा आपकी संख्या सीटी अजीब है - अंतिम समाधान को इसके बजाय एक पूर्ववर्ती संख्या तालिका का उपयोग करना चाहिए। अन्यथा, इस तरह मैं यह करूँगा। –

+0

एफवाईआई: "अजीब दिखना नहीं" एक मानदंड नहीं है कि मैं (या इस साइट पर उबेर-गीक्स के अधिकांश) वास्तव में परवाह करता हूं। और पूर्व-मौजूदा संख्या तालिका का उपयोग न करने का लाभ यह है कि यह तब भी काम करता है जब कहा गया तालिका पहले से मौजूद नहीं है (जो आमतौर पर नहीं होती है)। अंत में, यदि आप मेरे समाधान का परीक्षण करते हैं, तो आप पाएंगे कि यह पूर्व-मौजूदा संख्या तालिका से तुलनीय और कभी-कभी बेहतर प्रदर्शन करता है। – RBarryYoung

+0

मैं वास्तव में बहस नहीं करना चाहता - मैं ज्यादातर आपके समाधान से सहमत हूं। लेकिन "अजीब" आमतौर पर पढ़ने और अनजान करने में मुश्किल होती है। इस तरह मेरा मतलब था। यह भी DRY नहीं है यदि आपके पास दो अलग-अलग प्रश्न हैं जिनके लिए संख्याओं की आवश्यकता है - आपको दो बार अनजान सीटी लिखना होगा। System_columns के जुड़ने से पंक्ति संख्याओं को पढ़ना बहुत सरल नहीं है, लेकिन संख्या तालिका से पढ़ने की संख्या डीबग करना बहुत आसान होगा। –

40

मैं कभी कभी "अजीब" वर्ण

select 
    * 
from 
    <Table> 
where 
    <Field> != cast(<Field> as varchar(1000)) 
+0

यह मेरे लिए काम करता था और आरबीरीयॉन्ग के समाधान के बाद बहुत तेज़ था। – Trisped

+1

अगर यह संयोजन" गैर-ASCII "संयोजन पर सेट होता है तो यह काम नहीं करता है। – deerchao

+0

शानदार उत्तर –

1

खोजने के लिए इस "डाली" कथन का उपयोग किया गया है मैं @ CC1960 समाधान के साथ शुरू किया, लेकिन एक दिलचस्प उपयोग के मामले है कि यह विफल वजह से मिल गया।ऐसा लगता है कि SQL सर्वर कुछ यूनिकोड वर्णों को उनके गैर-यूनिकोड अनुमानों के बराबर समझाएगा। उदाहरण के लिए, WHERE क्लॉज की तुलना में SQL सर्वर यूनिकोड वर्ण "fullwidth अल्पविराम" (http://www.fileformat.info/info/unicode/char/ff0c/index.htm) मानक ASCII अल्पविराम के समान मानता है।

इसके आसपास पाने के लिए, SQL सर्वर स्ट्रिंग्स को द्विआधारी के रूप में तुलना करें। लेकिन याद रखें, nvarchar और varchar बाइनरी अप (बनाम 16 बिट 8 बिट) से मेल नहीं खाते, तो आप बाइनरी तुलना करने से पहले फिर से NVARCHAR करने के लिए अपनी varchar वापस बदलने की आवश्यकता:

select * 
from my_table 
where CONVERT(binary(5000),my_table.my_column) != CONVERT(binary(5000),CONVERT(nvarchar(1000),CONVERT(varchar(1000),my_table.my_column))) 
1

आप कर रहे हैं एक विशिष्ट यूनिकोड चरित्र की तलाश में, आप नीचे की तरह कुछ उपयोग कर सकते हैं।

select Fieldname from 
    (
     select Fieldname, 
      REPLACE(Fieldname COLLATE Latin1_General_BIN, 
      NCHAR(65533) COLLATE Latin1_General_BIN, 
      'CustomText123') replacedcol 
     from table 
    ) results where results.replacedcol like '%CustomText123%' 
2

यहाँ फिर जाना:

SELECT * 
FROM Objects 
WHERE 
    ObjectKey LIKE '%[^0-9a-zA-Z !"#$%&''()*+,\-./:;<=>[email protected]\[\^_`{|}~\]\\]%' ESCAPE '\' 
संबंधित मुद्दे