FOR JSON path在AZURE SQL上返回的行数较少

FOR JSON path在AZURE SQL上返回的行数较少,sql,azure-sql-database,sql-server-2016,Sql,Azure Sql Database,Sql Server 2016,我正在使用AZURE SQL(SQL Server 2016)并创建一个查询,以在JSON对象中为我提供输出。我在查询的末尾添加了JSON路径的 当我在没有向查询中添加JSON路径的的情况下执行该过程时,我得到244行(表中没有记录);但是,当我通过为JSON路径添加来执行该过程时,我得到了33行消息,并且还得到了被截断的JSON对象 我用不同类型的查询测试了这一点,包括仅选择10列的简单查询,但对于JSON路径,我总是得到较少的行数,并且JSON对象在末尾被截断 这是我的问题 SELECT

我正在使用AZURE SQL(SQL Server 2016)并创建一个查询,以在JSON对象中为我提供输出。我在查询的末尾添加了JSON路径的

当我在没有向查询中添加JSON路径的
的情况下执行该过程时,我得到244行(表中没有记录);但是,当我通过为JSON路径添加
来执行该过程时,我得到了33行消息,并且还得到了被截断的JSON对象

我用不同类型的查询测试了这一点,包括仅选择10列的简单查询,但对于JSON路径
,我总是得到较少的行数,并且JSON对象在末尾被截断

这是我的问题

SELECT 
    [Id]
    ,[countryCode]
    ,[CountryName]
    ,[FIPS]
    ,[ISO1]
    ,[ISO2]
    ,[ISONo]
    ,[capital]
    ,[region]
    ,[currency]
    ,[currencyCode]
    ,[population]
    ,[timeZone]
    ,[timeZoneCode]
    ,[ISDCode]
    ,[currencySymbol]
FROM 
    [dbo].[countryDB]
上面的查询返回2行

我使用下面的查询获得JSON格式的输出

SELECT 
    [Id]
    ,[countryCode]
    ,[CountryName]
    ,[FIPS]
    ,[ISO1]
    ,[ISO2]
    ,[ISONo]
    ,[capital]
    ,[region]
    ,[currency]
    ,[currencyCode]
    ,[population]
    ,[timeZone]
    ,[timeZoneCode]
    ,[ISDCode]
    ,[currencySymbol]
FROM 
    [dbo].[countryDB] 
FOR JSON PATH
上面的查询返回33行,输出为

[{"Id":1,"countryCode":"AD","CountryName":"Andorra","FIPS":"AN","ISO1":"AD","ISO2":"AND","ISONo":20,"capital":"Andorra la Vella","region":"Europe","currency":"Euro","currencyCode":"EUR","population":67627,"timeZone":2.00,"timeZoneCode":"DST","ISDCode":"+376"},{"Id":2,"countryCode":"AE","CountryName":"United Arab Emirates","FIPS":"AE","ISO1":"AE","ISO2":"ARE","ISONo":784,"capital":"Abu Dhabi","region":"Middle East","currency":"UAE Dirham","currencyCode":"AED","population":2407460,"timeZone":4.00,"timeZoneCode":"STD","ISDCode":"+971"},{"Id":3,"countryCode":"AF","CountryName":"Afghanistan","FIPS":"AF","ISO1":"AF","ISO2":"AFG","ISONo":4,"capital":"Kabul","region":"Asia","currency":"Afghani","currencyCode":"AFA","population":26813057,"timeZone":4.50,"timeZoneCode":"STD","ISDCode":"+93"},{"Id":4,"countryCode":"AG","CountryName":"Antigua and Barbuda","FIPS":"AC","ISO1":"AG","ISO2":"ATG","ISONo":28,"capital":"Saint Johns","region":"Central America and the Caribbean","currency":"East Caribbean Dollar","currencyCode":"205","population":66970,"timeZone":-4.00,"timeZoneCode":"STD","ISDCode":"+1"},{"Id":5,"countryCode":"AI","CountryName":"Anguilla","FIPS":"AV","ISO1":"AI","ISO2":"AIA","ISONo":660,"capital":"The Valley","region":"Central America and the Caribbean","currency":"East Caribbean Dollar","currencyCode":"205","population":12132,"timeZone":-4.00,"timeZoneCode":"STD","ISDCode":"+1"},{"Id":6,"countryCode":"AL","CountryName":"Albania","FIPS":"AL","ISO1":"AL","ISO2":"ALB","ISONo":8,"capital":"Tirana","region":"Europe","currency":"Lek","currencyCode":"ALL","population":3510484,"timeZone":2.00,"timeZoneCode":"DST","ISDCode":"+355"},{"Id":7,"countryCode":"AM","CountryName":"Armenia","FIPS":"AM","ISO1":"AM","ISO2":"ARM","ISONo":51,"capital":"Yerevan","region":"Commonwealth of Independent States","currency":"Armenian Dram","currencyCode":"AMD","population":3336100,"timeZone":5.00,"timeZoneCode":"DST","ISDCode":"+374"},{"Id":8,"countryCode":"AN","CountryName":"Netherlands Antilles","FIPS":"NT","ISO1":"AN","ISO2":

我试图直接在JSON中获取输出,当FOR JSON查询返回到客户端时,JSON文本作为一个单列结果集返回。JSON被分成固定长度的字符串,并通过多行发送

在SSMS中很难正确地看到这一点,因为SSMS在“结果到网格”中为您连接结果,并在“结果到文本”中截断每一行

为什么??不知道我的猜测是,只有.NET客户机知道如何高效地从SQL Server读取大数据流,99%的时间用户仍然只是缓冲整个对象。将JSON分解成多行,为客户机提供了一个简单的API来增量读取数据。在.NET中,事实上的标准JSON库不在BCL中,这意味着SqlClient不能真正拥有一流的JSON API

无论如何,在C#中,您可以使用类似的方法来读取结果:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp3
{
    class SqlJSONReader: TextReader
    {
        SqlDataReader rdr;
        string currentLine = "";
        int currentPos = 0;
        public SqlJSONReader(SqlDataReader rdr)
        {
            this.rdr = rdr;
        }
        public override int Peek()
        {
            return GetChar(false);
        }
        public override int Read()
        {
            return GetChar(true);
        }
        public  int GetChar(bool Advance)
        {
            while (currentLine.Length == currentPos)
            {
                if (!rdr.Read())
                {
                    return -1;
                }
                currentLine = rdr.GetString(0);
                currentPos = 0;
            }
            int rv =  (int)currentLine[currentPos];
            if (Advance) currentPos += 1;
            return rv;
        }

        public override void Close()
        {
            rdr.Close();
        }

    }

    class Program
    {

        static void Main(string[] args)
        {
            using (var con = new SqlConnection("server=.;database=master;Integrated Security=true"))
            {
                con.Open();
                var sql = @"
select o.object_id as [obj.Id], replicate('n', 2000) as [obj.foo], c.name as [obj.col.name]
from sys.objects o
join sys.columns c 
  on c.object_id = o.object_id
for json path;
"
;
                var cmd = new SqlCommand(sql, con);
                var sr = new StringBuilder();
                using (var rdr = cmd.ExecuteReader())
                {
                    using (var tr = new SqlJSONReader(rdr))
                    {
                        using (var jr = new Newtonsoft.Json.JsonTextReader(tr))
                        {
                           while (jr.Read())
                            {
                                Console.WriteLine($" {jr.TokenType} : {jr.Value}");
                            }
                        }

                    }

                }
                Console.WriteLine(sr.ToString());
            }



        }
    }
}

关注点的分离要求返回字符串并分别解析JSON。下面的代码段可以在不依赖JSON.net的情况下使用,JSON.net可以单独使用,也可以使用不同的JSON反序列化程序(例如,内置到RestSharp中的反序列化程序),并且不需要SqlJSONReader类

try {
     using (var conn = new SqlConnection(connectionString))
     using (var cmd = new SqlCommand(sql, conn)) {
        await conn.OpenAsync();
        logger.LogInformation("SQL:" + sql);
        var rdr = await cmd.ExecuteReaderAsync().ConfigureAwait(false);
        var result = "";
        var moreRows = rdr.HasRows;
        while (moreRows) {
            moreRows = await rdr.ReadAsync();
            if (moreRows) result += rdr.GetString(0);
        }
        return result;
     }
  }
  catch (Exception ex) {
     //logger.LogError($"Error accessing Db:{ex}");
     return null;
  }

for json path的sql查询结果是一个长字符串,分为多列或块 类似于这样的语句:“我想得到for json路径的结果”

每个块都等于sql中列的最大大小 所以只要把他们都列在一张清单上就行了

    public IHttpActionResult GetAdvertises()
    {

        var rEQUEST = db.Database.SqlQuery<string>("SELECT 
        ID,CITY_NAME,JSON_QUERY(ALBUM) AS ALBUM FOR JSON PATH").ToList();
        foreach(string req in rEQUEST)
        {
        HttpContext.Current.Response.Write(req);
        }

        return Ok();
    }
public IHttpActionResult GetAdvertises()
{
var rEQUEST=db.Database.SqlQuery(“选择
ID、城市名称、JSON查询(相册)作为JSON路径的相册”).ToList();
foreach(请求中的字符串请求)
{
HttpContext.Current.Response.Write(请求);
}
返回Ok();
}
感谢您。我发现我必须使用“打印”而不是“选择”

declare @json varchar(max) = (SELECT * FROM dbo.AppSettings FOR JSON AUTO)

print @json

如果您的查询返回超过2033个特许,那么将有行。每行包含2033个特许数据,另一行包含剩余数据。因此,您需要合并以获得实际的json。如下面代码示例所示

dynamic jsonReturned = unitOfWork
        .Database
        .FetchProc<string>("storedProcedureGetSaleData", new { ProductId = productId });

    if (Enumerable.Count(jsonReturned) == 0)
    {
        return null;
    }

    dynamic combinedJson = "";
    foreach (var resultJsonRow in jsonReturned)
    {
        combinedJson += resultJsonRow;
    }

    return combinedJsonResult;
dynamic jsonReturned=unitOfWork
数据库
.FetchProc(“storedProcedureGetSaleData”,新的{ProductId=ProductId});
if(Enumerable.Count(jsonReturned)==0)
{
返回null;
}
动态组合JSON=“”;
foreach(jsonReturned中的var resultJsonRow)
{
combinedJson+=resultJsonRow;
}
返回组合的JSONResult;

感谢您的解决方案,我一直在寻找是否有一种简单的方法可以在SQL Server级别处理它哦,很简单。只需将FOR JSON查询的结果分配给一个nvarchar(max)变量。例如declare@json-nvarchar(max)=(从sys.objects中选择*用于json-auto)谢谢David,它以我想要的方式完美工作。。。101%的分数给你请告诉我如何使用@DavidBrowne Microsoft solution获得结果。我刚刚收到一条短信,因为
命令成功完成。
?但是JSON输出在哪里?@Unbreakable-添加一行:select[atSign]JSON关注点在我发布的示例中完全分离。SqlJSONReader是文本阅读器(字符串的流视图)。如果返回一个字符串,则表示已将所有数据复制到内存中,这将无法实现将数据流传输到客户端的目的。
dynamic jsonReturned = unitOfWork
        .Database
        .FetchProc<string>("storedProcedureGetSaleData", new { ProductId = productId });

    if (Enumerable.Count(jsonReturned) == 0)
    {
        return null;
    }

    dynamic combinedJson = "";
    foreach (var resultJsonRow in jsonReturned)
    {
        combinedJson += resultJsonRow;
    }

    return combinedJsonResult;