मैं T-SQL में एक कस्टम JSON पार्सर लिख रहा हूँ † ।
अपने पार्सर के उद्देश्य के लिए, मैं उस PATINDEX
फ़ंक्शन का उपयोग कर रहा हूं जो टोकन की सूची से टोकन की स्थिति की गणना करता है। मेरे मामले में टोकन सभी एकल वर्ण हैं और इनमें ये शामिल हैं:
{} []:,
आमतौर पर, जब मुझे किसी दिए गए पात्रों में से किसी एक की पहली (पहली) स्थिति को खोजने की आवश्यकता होती है, तो मैं PATINDEX
इस तरह से फ़ंक्शन का उपयोग करता हूं :
PATINDEX('%[abc]%', SourceString)
समारोह तो मुझे के पहले की स्थिति दे देंगे a
या b
या c
में - जो भी पहले हो पाया होता है - SourceString
।
अब मेरे मामले में समस्या ]
चरित्र से जुड़ी हुई प्रतीत होती है । जैसे ही मैं इसे चरित्र सूची में निर्दिष्ट करता हूं, जैसे:
PATINDEX('%[[]{}:,]%', SourceString)
मेरा इरादा पैटर्न स्पष्ट रूप से टूट जाता है, क्योंकि फ़ंक्शन कभी भी मैच नहीं पाता है। ऐसा लगता है कि मुझे पहले से बचने का एक तरीका चाहिए ]
ताकि PATINDEX
इसे एक विशेष प्रतीक के बजाय लुकअप पात्रों में से एक माना जाए।
मैंने इस सवाल को एक समान समस्या के बारे में पूछा है:
हालांकि, उस मामले में ]
बस कोष्ठक में निर्दिष्ट करने की आवश्यकता नहीं है, क्योंकि यह सिर्फ एक चरित्र है और इसे उनके चारों ओर कोष्ठक के बिना निर्दिष्ट किया जा सकता है। वैकल्पिक समाधान, जो भागने का उपयोग करता है, केवल इसके लिए काम करता है LIKE
और इसके लिए नहीं PATINDEX
, क्योंकि यह एक ESCAPE
उपवर्ग का उपयोग करता है, पूर्व द्वारा समर्थित और बाद के द्वारा नहीं।
तो, मेरे सवाल है, वहाँ किसी भी तरह से एक के लिए देखने के लिए है ]
के साथ PATINDEX
का उपयोग कर [ ]
वाइल्डकार्ड? या अन्य ट्रांसेक्ट-एसक्यूएल टूल्स का उपयोग करके उस कार्यक्षमता का अनुकरण करने का एक तरीका है?
अतिरिक्त जानकारी
यहां एक क्वेरी का उदाहरण दिया गया है, जहां मुझे ऊपर दिए PATINDEX
गए […]
पैटर्न के साथ उपयोग करने की आवश्यकता है । यहां पैटर्न काम करता है (यद्यपि कुछ हद तक ) क्योंकि इसमें ]
चरित्र शामिल नहीं है । मुझे इसके साथ काम करने की आवश्यकता है ]
:
WITH
data AS (SELECT CAST('{"f1":["v1","v2"],"f2":"v3"}' AS varchar(max)) AS ResponseJSON),
parser AS
(
SELECT
Level = 1,
OpenClose = 1,
P = p.P,
S = SUBSTRING(d.ResponseJSON, 1, NULLIF(p.P, 0) - 1),
C = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0), 1),
ResponseJSON = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0) + 1, 999999)
FROM
data AS d
CROSS APPLY (SELECT PATINDEX('%[[{]%', d.ResponseJSON)) AS p (P)
UNION ALL
SELECT
Level = ISNULL(d.OpenClose - 1, 0) + d.Level + ISNULL(oc.OpenClose, 0),
OpenClose = oc.OpenClose,
P = d.P + p.P,
S = SUBSTRING(d.ResponseJSON, 1, NULLIF(p.P, 0) - 1),
C = c.C,
ResponseJSON = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0) + 1, 999999)
FROM
parser AS d
CROSS APPLY (SELECT PATINDEX('%[[{}:,]%' COLLATE Latin1_General_BIN2, d.ResponseJSON)) AS p (P)
CROSS APPLY (SELECT SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0), 1)) AS c (C)
CROSS APPLY (SELECT CASE WHEN c.C IN ('[', '{') THEN 1 WHEN c.C IN (']', '}') THEN 0 END) AS oc (OpenClose)
WHERE 1=1
AND p.P <> 0
)
SELECT
*
FROM
parser
OPTION
(MAXRECURSION 0)
;
मुझे जो आउटपुट मिलता है वह है:
Level OpenClose P S C ResponseJSON
----- --------- -- ----- -- ---------------------------
1 1 1 { "f1":["v1","v2"],"f2":"v3"}
1 null 6 "f1" : ["v1","v2"],"f2":"v3"}
2 1 7 [ "v1","v2"],"f2":"v3"}
2 null 12 "v1" , "v2"],"f2":"v3"}
2 null 18 "v2"] , "f2":"v3"}
2 null 23 "f2" : "v3"}
2 0 28 "v3" }
आप देख सकते हैं कि इसे पंक्तियों में से एक के ]
भाग के रूप में शामिल किया गया है S
। Level
स्तंभ, घोंसले ब्रैकेट अर्थ और ब्रेसिज़ नेस्टिंग के स्तर को दर्शाता है। जैसा कि आप देख सकते हैं, एक बार स्तर 2 हो जाने के बाद, यह कभी भी 1 पर नहीं लौटता है। ऐसा होता अगर मैं टोकन के रूप में PATINDEX
पहचान बना पाता ]
।
उपरोक्त उदाहरण के लिए अपेक्षित आउटपुट है:
Level OpenClose P S C ResponseJSON
----- --------- -- ---- -- ---------------------------
1 1 1 { "f1":["v1","v2"],"f2":"v3"}
1 NULL 6 "f1" : ["v1","v2"],"f2":"v3"}
2 1 7 [ "v1","v2"],"f2":"v3"}
2 NULL 12 "v1" , "v2"],"f2":"v3"}
2 0 17 "v2" ] ,"f2":"v3"}
1 NULL 18 , "f2":"v3"}
1 NULL 23 "f2" : "v3"}
1 0 28 "v3" }
आप इस क्वेरी के साथ db <> फिडल पर खेल सकते हैं ।
† हम एसक्यूएल सर्वर 2014 का उपयोग कर रहे हैं और जल्द ही एक संस्करण में अपग्रेड करने की संभावना नहीं है जो जेन्स को पार्सिंग का समर्थन करता है। मैं काम करने के लिए एक आवेदन लिख सकता था, लेकिन पार्सिंग के परिणामों को आगे संसाधित करने की आवश्यकता है, जो कि केवल पार्सिंग की तुलना में आवेदन में अधिक काम का अर्थ है - उस तरह का काम जो बहुत आसान होगा, और शायद अधिक कुशलता से, के साथ किया गया एक टी-एसक्यूएल स्क्रिप्ट, अगर केवल मैं इसे सीधे परिणामों पर लागू कर सकता हूं।
यह बहुत कम संभावना है कि मैं इस समस्या के समाधान के रूप में SQLCLR का उपयोग कर सकता हूं। हालांकि, मुझे कोई आपत्ति नहीं है अगर कोई SQLCLR समाधान पोस्ट करने का फैसला करता है, क्योंकि यह दूसरों के लिए उपयोगी हो सकता है।
["foo]bar”]
?