以下查詢非常冗長,因爲它包含用於演示查詢工作的外部select語句中的各個字段。要獲得正在運行的查詢,select語句只需要最右邊的列(即CASE ... END
語句)。
目的
寫來檢查,如果將BB區域的值是數字,如果是,用一個字符串替換它的SQL查詢。
下面的SQL查詢
在外部查詢的每一列表示在實現目標的漸進步驟,和這些步驟解釋如下。
注意:要獲得正在運行的查詢,select語句只需要最右邊的列(即CASE ... END
語句)。所有其他列不是必需的。
SELECT
json
-- Find the position of the JSON tag "bb": "
, PATINDEX(jsontagpattern, json)
-- Return the JSON data to the right of the JSON tag (right-half of the JSON)
, RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1)
-- Find the first double-quote from the right-half of the JSON
, PATINDEX(
'%"%',
RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1)
)
-- Return the value of the JSON tag "bb" based on the position of the double-quote found above
, LEFT(
RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1),
PATINDEX(
'%"%',
RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1)
) - 1
)
-- Check if the above value is numeric or not
, ISNUMERIC(
LEFT(
RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1),
PATINDEX('%"%', RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1)) - 1
)
)
-- Note: Only the following CASE expression is required, the previous expressions above were only to demonstrate the workings of the query
, CASE WHEN
ISNUMERIC(
LEFT(
RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1),
PATINDEX('%"%', RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1)) - 1
)
) = 1
THEN
-- The value is numeric, replace the value with 'replacetext'
STUFF(
json,
PATINDEX(jsontagpattern, json) + jsontaglength,
LEN(
LEFT(
RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1),
PATINDEX('%"%', RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1)) - 1
)
),
replacetext
)
ELSE json
END as OutputJson
FROM (
-- Sample data for demonstration purposes
-- Two JSON blocks, one where the field bb is numeric, one where it is not
SELECT
'{
"field1": "value1",
"block1": {
"aaa": "string",
"bb": "1234567890"
}
}' AS json
-- This expression is the string
-- %"bb": "
-- and is used for pattern matching
, '%' + '"bb": "' + '%' AS jsontagpattern
-- The length of the string used in pattern matching
, LEN( '"bb": "' ) AS jsontaglength
-- If the value of bb is numeric, replace it with the following text
, 'XXXX' AS replacetext
UNION
SELECT
'{
"field1": "value1",
"block1": {
"aaa": "string",
"bb": "1a23456789b0"
}
}' AS json
, '%' + '"bb": "' + '%' AS jsontagpattern
, LEN( '"bb": "' ) AS jsontaglength
, 'XXXX' AS replacetext
) AS x
說明
的第一步是找到bb
標籤的位置。這是由PATINDEX()
function完成:
PATINDEX(jsontagpattern, json)
下一步就是找到那就是標籤右側的JSON數據的一部分,因爲這會與BB字段的值開始。
RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1)
從上面的字符串返回,找到第一個雙引號,因爲它指示了BB的值結束:
PATINDEX( '%"%', RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1) )
獲取JSON場BB值(例如,返回1234567890):
LEFT( RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1), PATINDEX( '%"%', RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1) ) - 1 )
將ISNUMERIC()
function應用於上述值。如果它是數字則返回1,否則返回0。
如果ISNUMERIC()
返回0,則返回原始的JSON數據。但是,如果ISNUMERIC()
返回1,則使用STUFF()
function替換bb
字段的值。
採樣輸入&輸出
鑑於以下輸入:
{
"field1": "value1",
"block1": {
"aaa": "string",
"bb": "1234567890" <----- Numeric value
}
}
{
"field1": "value2",
"block1": {
"aaa": "string",
"bb": "1a23456789b0" <----- Non-numeric value
}
}
返回的輸出是:
{
"field1": "value1",
"block1": {
"aaa": "string",
"bb": "XXXX" <----- Numeric value replaced by string
}
}
{
"field1": "value2",
"block1": {
"aaa": "string",
"bb": "1a23456789b0" <----- Non-numeric value unchanged
}
}
你有一個SQL只提取和回「bb」字段的值?如果是,則使用T-SQL的['ISNUMERIC'](https://msdn.microsoft.com/en-us/library/ms186272.aspx)函數檢查它是否可以解釋爲數字,然後使用T-SQL的[字符串函數](https://msdn.microsoft.com/en-us/library/ms181984.aspx)來執行替換(即在值和連接之前/之後剪切左右部分中的字符串他們一起回來)。 – Phylyp
不,我沒有查詢提取此值 –
[本文](https://www.simple-talk.com/sql/t-sql-programming/consuming-json-strings-in-sql-服務器/)可能會有用。將它轉換爲表後,可以執行檢查。 – NEER