根据来自 json 个对象的数据过滤 table

Filter table based on data from json object

我正在尝试使用 JSONtype 作为存储过程的输入参数来对 return 数据进行一些过滤。

我有以下 TableA:

CREATE TABLE TableA (
   Id INT NULL,
   Value1 VARCHAR(25) NULL,
   Value2 VARCHAR(25) NULL
);

INSERT INTO TableA (Id, Value1, Value2) values (1, 'test1', 'new1')
INSERT INTO TableA (Id, Value1, Value2) values (1, 'test1', 'new2')
INSERT INTO TableA (Id, Value1, Value2) values (null, null, 'test3')
INSERT INTO TableA (Id, Value1, Value2) values (2, 'myvalue1', 'newvalue')

JSON 参数是动态的 - 表示一个或多个列名和来自上述 table 的值。

DECLARE @Filter NVARCHAR(MAX)
SET @Filter=N'{
  "Id": 2, 
  "Value1": "myvalue1",
  "Value2": "newvalue"
}'

然后我从 jsoninner join 中提取数据并使用 TableA 得到我需要的输出:

...
;WITH cte AS
(
   SELECT * FROM OPENJSON(@Filter)
   WITH(Id INT, 
        Value1 VARCHAR(25),
        Value2 VARCHAR(25))
)
SELECT a.* FROM cte ct
INNER JOIN TableA a
  ON ct.Id = a.Id
INNER JOIN TableA b
  ON ct.Value1 = b.Value1
INNER JOIN TableA c
  ON ct.Value2 = c.Value2

在这个特定示例中,我得到了所需的输出,因为我指定了所有列。然而,使用 JSON 作为参数的全部原因是能够动态传递不同的列(实际的 table 有更多的列)。

如果我要通过以下过滤器,我将不再获得所需的输出,因为 inner join

SET @Filter=N'{
  "Id": 2, 
}'
...
SET @Filter=N'{
  "Id": 2, 
  "Value1": "test1"
}'
...
SET @Filter=N'{
  "Value1": "test1, 
  "Value1": "new2"
}'
...etc
  1. 有没有办法动态地 select 来自 json 的所有具有值的对象并跳过空值?或者关于如何解决此问题的任何其他建议?
  2. 有没有办法检查 json 中是否有任何对象?根据文档,只有一个函数 ISJSON 可以验证以确保其格式正确。但是,如果我通过: SET @Filter=N'{}' 它是一个有效的 json 对象,但它是空的。

SQLFIDDLE

我知道这不是一个真正令人满意的答案,但我在这种情况下使用的方法是将每个可选字段与:

where (value1 is null or field1 = value1)

这消除了使用过滤器显式 select field1 is null 的能力,您将需要通过每个参数两个表达式来放大 select 语句:

--SELECT * FROM TableA

DECLARE @Filter NVARCHAR(MAX)
SET @Filter=N'{
  "Id": 1, 
  "Value1": "test1",
  "Value2": "new2"
}'
;WITH cte AS
(
  SELECT * FROM OPENJSON(@Filter)
  WITH(Id INT, 
       Value1 VARCHAR(25),
       Value2 VARCHAR(25))
)
SELECT a.* FROM cte filter
INNER JOIN TableA a
  ON     filter.Id = a.Id
     and (filter.Value1 is null or filter.Value1 = a.Value1)
     and (filter.Value2 is null or filter.Value2 = a.Value2)

查询结果

Id  Value1  Value2
1   test1   new2

过滤未设置值

如果您的 JSON 中有缺失值,这将不会用作过滤条件:

--SELECT * FROM TableA

DECLARE @Filter NVARCHAR(MAX)
SET @Filter=N'{
  "Id": 1, 
  "Value2": "new2"
}'
;WITH cte AS
(
  SELECT * FROM OPENJSON(@Filter)
  WITH(Id INT, 
       Value1 VARCHAR(25),
       Value2 VARCHAR(25))
)
SELECT a.* FROM cte filter
INNER JOIN TableA a
  ON     filter.Id = a.Id
     and (filter.Value1 is null or filter.Value1 = a.Value1)
     and (filter.Value2 is null or filter.Value2 = a.Value2)

SQL输出

Id  Value1  Value2
1   test1   new2

你可以试试这个:

SELECT a.* 
FROM TableA a
WHERE (a.Id IS NULL AND JSON_VALUE(@Filter,N'$.Id') IS NULL OR a.Id = ISNULL(CAST(JSON_VALUE(@Filter,N'$.Id') AS INT),a.Id))
  AND (a.Value1 IS NULL AND JSON_VALUE(@Filter,N'$.Value1') IS NULL OR a.Value1 = ISNULL(JSON_VALUE(@Filter,N'$.Value1'),a.Value1))
  AND (a.Value2 IS NULL AND JSON_VALUE(@Filter,N'$.Value2') IS NULL OR a.Value2 = ISNULL(JSON_VALUE(@Filter,N'$.Value2'),a.Value2));

诀窍是,用实际列的值替换 NULL...