it-swarm.com.de

Wie kann mithilfe von TSQL festgestellt werden, ob ein Schlüssel in einem JSON-Objekt vorhanden ist?

Dies ist eine interessante.

Stellen Sie sich vor, ich habe ein JSON-Objekt mit vier Schlüssel-Wert-Paaren, wobei die Schlüssel a, b, c und d sind.

Stellen Sie sich vor, dieses Objekt wird an eine gespeicherte Prozedur übergeben und jeder Schlüssel ist optional (solange sich mindestens 1 Schlüssel im Objekt befindet). Das heißt, es ist gültig, '{"a": "1"}' zu übergeben, obwohl b, c und d ausgeschlossen wurden.

Die Frage ist :

Wie kann ich in der gespeicherten Prozedur prüfen, ob ein bestimmter Schlüssel übergeben wurde?

Wenn ich versuche, mit json_value Auf einen Schlüssel zuzugreifen und der Schlüssel fehlt, erhalte ich im Lax-Modus einen null -Wert. Im strengen Modus erhalte ich eine Fehlermeldung. Ich nehme an, dies ist eine Möglichkeit, den Unterschied zu erkennen: Verweisen Sie auf den Schlüssel im strengen Modus und fangen Sie Fehler ab - aber ich möchte die Verwendung der Try-Catch-Logik vermeiden.

Nachfolgend einige Beispielaufrufe:

declare @data nvarchar(max); set @data = N'{"a":"1","b":"","c":null}';
select [value] from openjson(@data);
select 'strict a', json_value(@data, 'strict $.a') union
select 'strict b', json_value(@data, 'strict $.b') union
select 'strict c', json_value(@data, 'strict $.c') union
-- select 'strict d', json_value(@data, 'strict $.d') union
select 'lax a', json_value(@data, 'lax $.a') union
select 'lax b', json_value(@data, 'lax $.b') union
select 'lax c', json_value(@data, 'lax $.c') union
select 'lax d', json_value(@data, 'lax $.d');

Das zeigt:

  • Ein Zeichenfolgenwert ungleich Null wird immer "wie besehen" zurückgegeben (Schlüssel 'a').
  • Eine leere Zeichenfolge wird immer "wie sie ist" zurückgegeben (Schlüssel 'b').
  • Eine Null wird immer "wie sie ist" zurückgegeben (Schlüssel 'c')
  • Ein fehlender Schlüssel wird im laxen Modus als null zurückgegeben. Wenn Sie die entsprechende Zeile auskommentieren, wird beim Versuch, im strengen Modus auf einen fehlenden Schlüssel zu verweisen, ein Fehler zurückgegeben.

Mit anderen Worten, ich kann nicht zwischen einem fehlenden Schlüssel und einem Schlüssel unterscheiden, der mit einem Nullwert versehen wurde.

Warum möchte ich den Unterschied zwischen der Übergabe von Null und dem Fehlen eines Schlüssels unterscheiden? Wenn der Schlüssel vorhanden ist, sollte sein Wert beibehalten werden (ob null oder nicht). Ich möchte nicht null beibehalten, falls der Schlüssel fehlt. Wenn der Schlüssel nicht vorhanden ist, möchte ich einfach nichts in Bezug auf diesen Schlüssel (oder die Spalte, in der sein Wert beibehalten wird) tun.

Mein nächster Ansatz bestand darin, mich zu fragen, ob ich die übereinstimmenden Zeilen zählen könnte - vielleicht würde die Zählfunktion anstelle eines Fehlers '0' als Anzahl der auf Schlüssel 'd' übereinstimmenden Zeilen zurückgeben.

Hier wird es interessant.

declare @data nvarchar(max); set @data = N'{"a":"1","b":"","c":null}';

with CTE as (select json_value(@data, 'strict $.a') as strictA)
select count(1) from CTE;

with CTE2 as (select json_value(@data, 'strict $.d') as strictD)
select count(1) from CTE2;

Ich hatte gehofft, die Werte 1 und 0 zu sehen. Ich dachte, es wäre entweder das oder es würde einen Fehler auslösen. Das tatsächliche Ergebnis ist, dass beide Abfragen eine Anzahl von 1 zurückgeben.

Warum gibt die zweite Abfrage '1' zurück?

Und muss ich auf die Try-Catch-Logik zurückgreifen, um festzustellen, ob ein bestimmter Schlüssel in einem JSON-Fragment vorhanden ist?

2

Versuchen Sie stattdessen OPENJSON . Dies gibt eine Typspalte zurück, die einen NULL-Wert für einen Schlüssel angibt. Sie können dies mit einer Quellliste möglicher Schlüssel verknüpfen und nach einem NULL-Typwert oder einem NULL-Rückgabewert suchen, um festzustellen, ob der Schlüssel vorhanden ist oder nicht. Beispiel unten:

declare @data nvarchar(max); set @data = N'{"a":"1","b":"","c":null}';

SELECT [Value],
    CASE 
        WHEN [type] IS NULL THEN 'Not Present'
        WHEN [type] = 0 THEN 'Null Value'
        ELSE 'Non-Null Value'
    END AS [KeyPresent]
FROM
(
    SELECT 'a' AS [key]
    UNION
    SELECT 'b' AS [key]
    UNION
    SELECT 'c' AS [key]
    UNION
    SELECT 'd' AS [key]
) keys
LEFT JOIN OPENJSON(@data) jdata ON keys.[key] = jdata.[key]
2
HandyD

... Eigentlich nur noch ein paar Minuten Arbeit und ich fand eine Antwort, nämlich:

declare @data nvarchar(max); set @data = N'{"a":"1","b":"","c":null}';

select 'checking a ', case when 'a' in (select [key] from openjson(@data)) then 'present' else 'absent' end union
select 'checking d', case when 'd' in (select [key] from openjson(@data)) then 'present' else 'absent' end;

Wählen Sie einfach alle Schlüssel aus und prüfen Sie, ob sich Ihr gewünschter Schlüssel in der Ergebnismenge befindet.

1