2017-03-22 11 views
2

In meinem Tisch habe ich eine Spalte, die ein json enthält:sql: prüfen, ob ein Teil numerisch ist und ersetzen Sie es

{ 
    "field1": "value1", 
    "block1": { 
     "aaa": "string", 
     "bb": "1234567890" 
    } 
} 

Wie eine SQL-Abfrage schreiben, die der Wert von bb Feld überprüft, ob numerisch und Wenn ja, ersetzen Sie es durch eine Zeichenfolge?

Das Ergebnis wäre wie:

{ 
    "field1": "value1", 
    "block1": { 
     "aaa": "string", 
     "bb": "xxxxxxxxxx" 
    } 
} 

Bitte beachten Sie, dass die json andere Blöcke vor dem block1 enthalten.

Ich verwende SQL server 2014.

+0

Haben Sie eine SQL müssen nur extrahieren und Rückkehr der Wert des 'bb'-Feldes? Wenn ja, dann verwenden Sie die Funktion ['ISNUMERIC'] von T-SQL (https://msdn.microsoft.com/en-us/library/ms186272.aspx), um zu prüfen, ob sie als Zahl interpretiert werden kann, und verwenden Sie sie dann T-SQLs [string-Funktionen] (https://msdn.microsoft.com/en-us/library/ms181984.aspx), um die Ersetzung durchzuführen (dh die Zeichenfolge in einem linken und rechten Teil vor/nach dem Wert zu schneiden und zu verketten sie wieder zusammen). – Phylyp

+0

Nein, ich habe keine Abfrage, um diesen Wert zu extrahieren –

+1

[Dieser Artikel] (https://www.simple-talk.com/sql/t-sql-programming/consuming-json-strings-in-sql- Server /) kann nützlich sein. Sie können die Prüfungen durchführen, nachdem Sie sie in eine Tabelle konvertiert haben. – NEER

Antwort

0

Die folgende Abfrage ist ziemlich lang, da sie verschiedene Felder in der äußeren SELECT-Anweisung enthält, die zum Veranschaulichen der Funktionsweise der Abfrage verwendet wird. Um nur eine funktionierende Abfrage zu erhalten, benötigt die select-Anweisung nur die ganz rechte Spalte (d. H. Die -Anweisung).

Ziel

eine SQL-Abfrage schreiben, dass der Wert des bb Feld überprüft, ob numerisch ist und wenn es ist, ersetzen Sie es mit einer Schnur.

die SQL-Abfrage

Jede Spalte in der äußeren Abfrage unten zeigt einen progressiven Schritt in das Ziel zu erfüllen, und diese Schritte werden im Folgenden erläutern.

Hinweis: Um nur eine funktionierende Abfrage zu erhalten, benötigt die select-Anweisung nur die ganz rechte Spalte (d. H. Die -Anweisung). Alle anderen Spalten sind nicht erforderlich.

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 

Erklärung

  1. Der erste Schritt ist die Position des bb Tag zu finden. Dies wird durch die PATINDEX() function getan:

    PATINDEX(jsontagpattern, json)

  2. Der nächste Schritt ist es, den Teil der JSON-Daten zu finden, die rechts von dem Tag, da dies mit dem bb Feldwert beginnen.

    RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1)

  3. Aus der Zeichenfolge oben zurück, die ersten doppelten Anführungszeichen finden, da es zeigt an, wo der Wert von bb endet:

    PATINDEX( '%"%', RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1) )

  4. den Wert des Feldes bb JSON Get mit den folgenden (das gibt beispielsweise 1234567890 zurück):

    LEFT( RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1), PATINDEX( '%"%', RIGHT(json, LEN(json) - PATINDEX(jsontagpattern, json) - jsontaglength + 1) ) - 1 )

  5. Wenden Sie die ISNUMERIC() function auf den obigen Wert an. Es gibt 1 zurück, wenn es numerisch ist, andernfalls 0.

  6. Wenn ISNUMERIC() 0 zurückgibt, geben Sie die ursprünglichen JSON-Daten zurück. Wenn jedoch ISNUMERIC() den Wert 1 zurückgibt, ersetzen Sie den Wert des Felds bb mit STUFF() function.

Probeneingang & Ausgang

Angesichts der folgenden Eingabe:

{ 
     "field1": "value1", 
     "block1": { 
      "aaa": "string", 
      "bb": "1234567890"  <----- Numeric value 
     } 
    } 
{ 
     "field1": "value2", 
     "block1": { 
      "aaa": "string", 
      "bb": "1a23456789b0"  <----- Non-numeric value 
     } 
    } 

Der Ausgang zurückgekehrt ist:

{ 
     "field1": "value1", 
     "block1": { 
      "aaa": "string", 
      "bb": "XXXX"    <----- Numeric value replaced by string 
     } 
    } 
{ 
     "field1": "value2", 
     "block1": { 
      "aaa": "string", 
      "bb": "1a23456789b0"  <----- Non-numeric value unchanged 
     } 
    } 
0

Gefunden dies eine schwierige Aufgabe ist, geht so hier:

Zuerst eine Funktion erstellen, die die Werte für bb zurückgibt:

CREATE FUNCTION fn_getBB(@str NVARCHAR(1000)) 
RETURNS NVARCHAR(1000) 
AS 
BEGIN 
DECLARE @ret NVARCHAR(1000) 
SELECT @ret = (LEFT(RIGHT(@str,len(@str) - CHARINDEX('"bb": ', @str) - 6),  CHARINDEX('"',RIGHT(@str,len(@str) - CHARINDEX('"bb": ', @str) - 7),2))) 
RETURN @ret; 
END 

Es kann ohne es getan werden, aber es wird nicht lesbar , gelinde gesagt.

Danach können Sie es wie folgt testen:

DECLARE @str nvarchar(1000) 
SET @str = 'whatevertexthere "bb": "1237777" whateverothertextherexxx' 

SELECT REPLACE(@str, '"bb": "'+dbo.fn_getBB(@str)+'"','"bb": "'+ 'ana are mere"') 
WHERE ISNUMERIC(dbo.fn_getBB(@str)) = 1 

Wenn die Tests ok aussehen, einfach eine UPDATE auf dem Tisch mit der gleichen WHERE Klausel ausführen (WHERE ISNUMERIC(dbo.fn_getBB(@str)) = 1)

Hoffe, es hilft!

PS - die Funktion setzt voraus, dass in Ihrem JSON immer ein "bb" vorhanden ist. Wenn dies nicht der Fall ist, können Sie es immer als Bedingung in Ihrer WHERE-Klausel angeben.

PPS - Wenn Sie die Tabelle nicht aktualisieren, sondern einfach den Wert für bb in Ihrer Ergebnismenge ersetzen möchten, verwenden Sie SELECT CASE WHEN ISNUMERIC(fn_getBB(yourjsoncol)) = 1 THEN REPLACE ... ELSE yourjsoncol ....

Verwandte Themen