我正在尝试使用JSON
type作为存储过程的输入参数,对返回数据进行一些过滤。
我有以下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
参数是动态的-代表上表中的一个或多个列名称和值。
DECLARE @Filter NVARCHAR(MAX)
SET @Filter=N'{
"Id": 2,
"Value1": "myvalue1",
"Value2": "newvalue"
}'
然后我从json
提取数据,并用inner 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
作为参数的全部原因是为了能够动态传递不同的列(实际表具有更多的列)。
如果我要通过以下过滤器,由于inner join
,我将不再获得所需的输出。
SET @Filter=N'{
"Id": 2,
}'
...
SET @Filter=N'{
"Id": 2,
"Value1": "test1"
}'
...
SET @Filter=N'{
"Value1": "test1,
"Value1": "new2"
}'
...etc
ISJSON
会进行验证以确保其格式正确。但是,如果我通过:SET @Filter=N'{}'
,则它是有效的json对象,但为空。 答案 0 :(得分:2)
您可以尝试以下方法:
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
...
答案 1 :(得分:0)
我知道这并不是一个令人满意的答案,但是我在这种情况下使用的方法是将每个可选字段与:
where (value1 is null or field1 = value1)
这消除了使用过滤器显式选择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)
Id Value1 Value2
1 test1 new2