गैर-अंक LIKE [0-9] क्यों हैं?


13

इस क्वेरी द्वारा निर्धारित मेरे सर्वर का डिफ़ॉल्ट टकराव लैटिन 1_General_CI_AS है:

SELECT SERVERPROPERTY('Collation') AS Collation;

मुझे यह जानकर आश्चर्य हुआ कि इस टकराव से मैं विधेय का उपयोग करते हुए तार में गैर-अंकीय वर्णों का मिलान कर सकता हूं LIKE '[0-9]'

डिफ़ॉल्ट कोलाजेशन में ऐसा क्यों होता है? मैं ऐसे मामले के बारे में नहीं सोच सकता जहाँ यह उपयोगी होगा। मुझे पता है कि मैं बाइनरी कॉलेशन का उपयोग करके व्यवहार के चारों ओर काम कर सकता हूं, लेकिन यह डिफ़ॉल्ट कॉलेशन को लागू करने के लिए एक अजीब तरीके की तरह लगता है।

फ़िल्टरिंग अंक गैर-अंक वाले कैक्टर्स का उत्पादन करते हैं

मैं एक कॉलम बनाकर व्यवहार को प्रदर्शित कर सकता हूं जिसमें सभी संभव एकल-बाइट चरित्र मान शामिल हैं और अंकों को मिलान करने वाले विधेय के साथ मानों को फ़िल्टर करना है।

निम्न कथन 256 पंक्तियों के साथ एक अस्थायी तालिका बनाता है, जो वर्तमान कोड पृष्ठ के प्रत्येक कोड बिंदु के लिए है:

WITH P0(_) AS (SELECT 0 UNION ALL SELECT 0),
P1(_) AS (SELECT 0 FROM P0 AS L CROSS JOIN P0 AS R),
P2(_) AS (SELECT 0 FROM P1 AS L CROSS JOIN P1 AS R),
P3(_) AS (SELECT 0 FROM P2 AS L CROSS JOIN P2 AS R),
Tally(Number) AS (
  SELECT -1 + ROW_NUMBER() OVER (ORDER BY (SELECT 0))
  FROM P3
)
SELECT Number AS CodePoint, CHAR(Number) AS Symbol
INTO #CodePage
FROM Tally
WHERE Number >= 0 AND Number <= 255;

प्रत्येक पंक्ति में कोड बिंदु का पूर्णांक मान और कोड बिंदु का वर्ण मान होता है। सभी वर्ण मान प्रदर्शित नहीं होते हैं - कुछ कोड बिंदु कड़ाई से वर्णों को नियंत्रित करते हैं। यहाँ के उत्पादन का एक चयनात्मक नमूना है SELECT CodePoint, Symbol FROM #CodePage:

0   
1   
2   
...
32   
33  !
34  "
35  #
...
48  0
49  1
50  2
...
65  A
66  B
67  C
...
253 ý
254 þ
255 ÿ

मैं उम्मीद करता हूं कि प्रतीक कॉलम पर एक LIKE विधेय का उपयोग करके अंक वर्ण खोजने के लिए और '0' के माध्यम से वर्णों की श्रेणी निर्दिष्ट करने में सक्षम होने की उम्मीद करूंगा: '9'

SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]';

यह एक आश्चर्यजनक उत्पादन का उत्पादन करता है:

CodePoint   Symbol
48  0
49  1
50  2
51  3
52  4
53  5
54  6
55  7
56  8
57  9
178 ²
179 ³
185 ¹
188 ¼
189 ½
190 ¾

कोड अंक 48 के सेट के माध्यम से 57 मैं उम्मीद कर रहे हैं। मेरे लिए आश्चर्य की बात यह है कि परिणाम के सेट में सुपरस्क्रिप्ट और अंशों के प्रतीकों को भी शामिल किया गया है!

संख्या के रूप में प्रतिपादकों और अंशों के बारे में सोचने का एक गणितीय कारण हो सकता है, लेकिन उन्हें अंक कहना गलत लगता है।

बाइनरी कॉलेशन को वर्कअराउंड के रूप में उपयोग करना

मैं समझता हूं कि मुझे उम्मीद है कि परिणाम प्राप्त करने के लिए, मैं इसी द्विआधारी टक्कर लैटिन 1_General_BIN को मजबूर कर सकता हूं:

SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]' COLLATE Latin1_General_BIN;

परिणाम सेट में केवल ५ 57 अंक ५ set शामिल हैं:

CodePoint   Symbol
48  0
49  1
50  2
51  3
52  4
53  5
54  6
55  7
56  8
57  9

जवाबों:


22

[0-9] केवल मिलान अंकों के लिए परिभाषित कुछ प्रकार की नियमित अभिव्यक्ति नहीं है।

एक LIKEपैटर्न में कोई भी श्रेणी कोलाजेशन क्रम के अनुसार शुरू और अंत चरित्र के बीच के पात्रों से मेल खाती है।

SELECT CodePoint,
       Symbol,
       RANK() OVER (ORDER BY Symbol COLLATE Latin1_General_CI_AS) AS Rnk
FROM   #CodePage
WHERE  Symbol LIKE '[0-9]' COLLATE Latin1_General_CI_AS
ORDER  BY Symbol COLLATE Latin1_General_CI_AS 

रिटर्न

CodePoint            Symbol Rnk
-------------------- ------ --------------------
48                   0      1
188                  ¼      2
189                  ½      3
190                  ¾      4
185                  ¹      5
49                   1      5
50                   2      7
178                  ²      7
179                  ³      9
51                   3      9
52                   4      11
53                   5      12
54                   6      13
55                   7      14
56                   8      15
57                   9      16

इसलिए आपको ये परिणाम मिलते हैं क्योंकि आपके डिफ़ॉल्ट टकराव के तहत ये वर्ण बाद में 0लेकिन पहले होते हैं 9

ऐसा लगता है कि जैसे टकराव को परिभाषित किया गया है वास्तव में गणितीय क्रम में उन्हें छांटने के बीच के क्रम में भिन्न के साथ 0और 1

आप एक सीमा के बजाय एक सेट का उपयोग भी कर सकते हैं। 2मिलान से बचने के लिए ²आपको एक CSटकराव की आवश्यकता होगी

SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0123456789]' COLLATE Latin1_General_CS_AS

6

लेटिन 1 कोड पेज 1252 है, जिसमें 178 'सुपरसिप्ट टू' है । यह एक यूनिकोड सुपरस्क्रिप्ट है : सुपरस्क्रिप्ट के रूप में "2" वर्ण हैयूनिकोड टेक्निकल स्टैंडर्ड # 10 के अनुसार इसकी तुलना 2 के बराबर होनी चाहिए, 8.1 Collation Folding देखें :

नक्शा संगतता (तृतीयक) समकक्ष, जैसे पूर्ण-चौड़ाई और सुपरस्क्रिप्ट वर्ण , प्रतिनिधि चरित्र के लिए

बग होगा यदि सुपरस्क्रिप्ट 2 2 से अलग तुलना करेगा! आपके कहने से पहले 'लेकिन मेरा कॉलम यूनिकोड नहीं है', निश्चिंत रहें: MSDN (Windows Collations देखें) के अनुसार सभी स्ट्रिंग तुलना और छँटाई यूनिकोड नियमों के अनुसार की जाती है, तब भी जब ऑन-डिस्क प्रतिनिधित्व CHAR होता है।

आपके उदाहरण में अन्य पात्रों के लिए, जैसे VULGAR FRACTION ONE QUARTERऔर जैसे वे किसी भी संख्या के बराबर की तुलना नहीं करते हैं, लेकिन, जैसा कि मार्क ने पहले ही दिखाया था, वे 0 और 9 के बीच ठीक तरह से करते हैं।

और, ज़ाहिर है, यदि आप कोड पृष्ठ को बदलते हैं तो आपको अलग-अलग परिणाम प्राप्त होंगे। उदाहरण के लिए। साथ Greek_CS_AS( कोड पेज 1253 ) आप कोड 178, 179 और 189 के साथ पात्रों मिलेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.