T-SQL †でカスタムJSONパーサーを作成しています。
私のパーサーのために、PATINDEX
トークンのリストからトークンの位置を計算する関数を使用しています。私の場合のトークンはすべて1文字で、次のものが含まれています。
{} []:、
通常、与えられたいくつかの文字の(最初の)位置を見つける必要があるときは、次のPATINDEX
ような関数を使用します。
PATINDEX('%[abc]%', SourceString)
この関数はその後、私の最初の位置を与えるa
か、b
またはc
に-最初に発見される早い方- SourceString
。
今、私の場合の問題は]
キャラクターに関連しているようです。文字リストで指定するとすぐに、たとえば次のようになります。
PATINDEX('%[[]{}:,]%', SourceString)
関数が一致を見つけられないため、私の意図したパターンは明らかに壊れています。私が最初に脱出する方法が必要ですように見えます]
ので、PATINDEX
検索文字ではなく、特別なシンボルの一つとして扱い、それを。
私は同様の問題について尋ねるこの質問を見つけました:
ただし、その場合、]
単に1文字であり、大括弧なしで指定できるため、大括弧で指定する必要はありません。エスケープ使用しない別の解決策は、だけのために働くLIKE
といないためPATINDEX
、それが使用しているため、ESCAPE
後者によって前者としないことによってサポートされ、副次句を。
だから、私の質問は、ワイルドカードを使用してを探す方法はありますか?]
PATINDEX
[ ]
または、他のTransact-SQLツールを使用してその機能をエミュレートする方法はありますか?
追加情報
上記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 <> fiddleで試すことができます。
† SQL Server 2014を使用しており、JSON解析をネイティブでサポートするバージョンにすぐにアップグレードすることはほとんどありません。仕事をするアプリケーションを書くことはできますが、解析の結果をさらに処理する必要があります。これは、解析だけではなく、アプリケーションでより多くの作業が必要であることを意味します。 T-SQLスクリプト(結果に直接適用できる場合のみ)。
この問題の解決策としてSQLCLRを使用できる可能性はほとんどありません。ただし、誰かがSQLCLRソリューションを投稿することを決定してもかまいません。
["foo]bar”]
ですか?