问题 where 子句 FOR JSON AUTO 生成了不完整的答案

Ale*_*ley 0 t-sql sql-server

从 SQL Server 获取 JSON 很棒,但我遇到了问题。例子。我有一个LithologySamples具有非常基本结构的表:

    [Id] [uniqueidentifier],
    [Depth1] [real],
    [Depth2] [real],
    [RockId] [nvarchar](8),
Run Code Online (Sandbox Code Playgroud)

数据库中该表大约有 600 条记录。我想生成 JSON 以将数据传输到另一个数据库,因此我使用FOR JSON AUTO. 这与其他记录较少的表完美配合。但在这种情况下,我发现生成的响应不完整。让我很困惑。我在检查输出时注意到:

    [Id] [uniqueidentifier],
    [Depth1] [real],
    [Depth2] [real],
    [RockId] [nvarchar](8),
Run Code Online (Sandbox Code Playgroud)

我已经搜索过,但找不到任何选项来完整地给出答案。

SQL查询如下:

[{
        "Id": "77769039-B2B7-E511-8279-DC85DEFBF2B6",
        "Depth1": 4.2000000e+001,
        "Depth2": 5.8000000e+001,
        "RockId": "MIC SST"
    }, {
        "Id": "78769039-B2B7-E511-8279-DC85DEFBF2B6",
        "Depth1": 5.8000000e+001,
        "Depth2": 6.3000000e+001,
        "RockId": "CGL"
    }, {
        "Id": "79769039-B2B7-E511-8279-DC85DEFBF2B6",
        "Depth1": 6.3000000e+001,
        "Depth2": 8.3000000e+001,
        "RockId": "MIC SST"
    }, {
// ... OK, continue fine, but it breaks off towards the end:
    }, {
        "Id": "85769039-B2B7-E511-8279-DC85DEFBF2B6",
        "Depth1": 2.0500000e+002,
        "Depth2": 2.1500000e+002,
        "RockId": "MIC SST"
    }, {
        "Id": "86769039-
// inexplicably it cuts here !?

Run Code Online (Sandbox Code Playgroud)

AUTO 或 PATH 是相同的结果

有谁知道我应该做什么才能使该语句生成整个表的 JSON?

Aar*_*and 5

但在这种情况下,我发现生成的响应不完整。

如果您在 SSMS 中检查此项,它会根据您使用的输出方法(PRINTSELECT、结果到文本/网格)以各种方式截断文本。字符串是完整的,只是输出被破坏了。

验证字符串确实完整的一种方法是:

SELECT * INTO #foo FROM 
  (SELECT * FROM LithologySamples FOR JSON AUTO) x(y);
Run Code Online (Sandbox Code Playgroud)

然后检查LEN(y), DATALENGTH(y), RIGHT(y , 50)(请参阅示例 db<>fiddle),或使用从CONVERT(xml表中进行选择(有关更多信息,请参阅本文)。

在您的情况下,问题似乎出在 C# 如何消耗输出。如果消费者将 JSON 视为多行,那么在那里分配一个变量最终将分配 <= 2033 个字符的任意行,而不是整个值。我在 2015 年曾简单谈过这一点。假设您正在使用reader[0]或类似于测试:

CREATE TABLE dbo.Samples
(
    [Id] [uniqueidentifier] NOT NULL DEFAULT NEWID(),
    [Depth1] [real] NOT NULL DEFAULT 5,
    [Depth2] [real] NOT NULL DEFAULT 5,
    [RockId] [nvarchar](8)
);

INSERT dbo.Samples(RockId) SELECT TOP (100) LEFT(name, 8) FROM sys.all_columns;

-- pretend this is your C# reader:
SELECT * FROM dbo.Samples FOR JSON AUTO;

-- reader[0] here would be something like this:
-- [{"Id":"054EC9A2-760B-4EBA-BF06-...,"RockId":"ser

-- which is the first 2,033 characters
SELECT LEN('[{"Id":"054EC9A2-760B-4EBA-BF06-..."RockId":"ser')

-- instead, since you want C# to assign a scalar, 
-- assign output to a scalar first:
DECLARE @json nvarchar(max) = (SELECT * FROM dbo.Samples FOR JSON AUTO);
SELECT json = @json;

-- now reader[0] will be the whole thing
Run Code Online (Sandbox Code Playgroud)

2033 与 XML 的来源相同(因为 SQL Server 的 JSON 实现只是现有底层 XML 功能的一个漂亮包装器),正如 Charlie 指出的,Martin 在这里解释道: