在 SQL Select 中连接字符串
Concat string in SQL Select
我有以下 TSQL:
SELECT
Id,
CAST('' as XML).value('xs:base64Binary(sql:column("Content"))', 'NVARCHAR(MAX)') + '=' as Content,
Name
FROM Files
ORDER BY Id
未在内容值列的末尾添加字符“=”。我也试过:
SELECT
Id,
CONCAT(CAST('' as XML).value('xs:base64Binary(sql:column("Content"))', 'NVARCHAR(MAX)'), '=') as Content,
Name
FROM Files
ORDER BY Id
同样的问题...字符串末尾没有添加字符'='。
我错过了什么?
The character '=' is not being added at the end of the column
当然是。 SSMS 可能正在截断该值。但是你不应该首先在末尾添加'='。这是 base64 规范的一部分,xml.value() 将根据需要添加“=”或“==”来填充值。在末尾添加'='将产生无效的base64字符串,例如:
use tempdb
go
drop table if exists Files
go
create table Files(id int primary key, name varchar(200), Content varbinary(max))
go
insert into Files(id,name,Content) values (1,'1',0x9789798d7987907a09797a987908790787897b0987d9087097e09879087d907907097097a0c0909890809789798798789798707097090)
SELECT
Id,
CAST('' as XML).value('xs:base64Binary(sql:column("Content"))', 'NVARCHAR(MAX)') + '=' as Content,
Name
FROM Files
ORDER BY Id
/*
CXiXmNeYeQegl5eph5CHkHh4l7CYfZCHCX4Jh5CH2QeQcJcJegwJCYkICXiXmHmHiXmHBwlwkA===
*/
这是一个比较 .NET 和 SQL 服务器的 base64 编码的示例:
using System;
using System.Data;
using System.Linq;
using System.Data.SqlClient;
namespace netcore3test
{
class File
{
public byte[] Content { get; set; }
}
class Program
{
static void Main(string[] args)
{
var maxLen = 1024 * 1024;
using var con = new SqlConnection("server=localhost;database=tempdb;integrated security=true");
con.Open();
var cmd = con.CreateCommand();
cmd.CommandText = @"
with q as (select @buf Content)
select CAST('' as XML).value('xs:base64Binary(sql:column(""Content""))', 'NVARCHAR(MAX)') base64string
from q
";
var pBuf = cmd.Parameters.Add("@buf", SqlDbType.VarBinary, -1);
var rand = new Random(0);
;
for (int len = 0; len < maxLen; len++)
{
var buf = new byte[len];
rand.NextBytes(buf);
pBuf.Value = buf;
var netBase64 = Convert.ToBase64String(buf);
var sqlBase64 = (string)cmd.ExecuteScalar();
var json = @$"{{""Content"" : ""{sqlBase64}"" }}";
var File = System.Text.Json.JsonSerializer.Deserialize<File>(json);
var sqlBuf = File.Content;
if (!buf.SequenceEqual(sqlBuf) || netBase64 != sqlBase64)
{
Console.WriteLine($"Fail {netBase64} {sqlBase64}");
}
Console.WriteLine(sqlBase64);
}
}
}
}
我有以下 TSQL:
SELECT
Id,
CAST('' as XML).value('xs:base64Binary(sql:column("Content"))', 'NVARCHAR(MAX)') + '=' as Content,
Name
FROM Files
ORDER BY Id
未在内容值列的末尾添加字符“=”。我也试过:
SELECT
Id,
CONCAT(CAST('' as XML).value('xs:base64Binary(sql:column("Content"))', 'NVARCHAR(MAX)'), '=') as Content,
Name
FROM Files
ORDER BY Id
同样的问题...字符串末尾没有添加字符'='。
我错过了什么?
The character '=' is not being added at the end of the column
当然是。 SSMS 可能正在截断该值。但是你不应该首先在末尾添加'='。这是 base64 规范的一部分,xml.value() 将根据需要添加“=”或“==”来填充值。在末尾添加'='将产生无效的base64字符串,例如:
use tempdb
go
drop table if exists Files
go
create table Files(id int primary key, name varchar(200), Content varbinary(max))
go
insert into Files(id,name,Content) values (1,'1',0x9789798d7987907a09797a987908790787897b0987d9087097e09879087d907907097097a0c0909890809789798798789798707097090)
SELECT
Id,
CAST('' as XML).value('xs:base64Binary(sql:column("Content"))', 'NVARCHAR(MAX)') + '=' as Content,
Name
FROM Files
ORDER BY Id
/*
CXiXmNeYeQegl5eph5CHkHh4l7CYfZCHCX4Jh5CH2QeQcJcJegwJCYkICXiXmHmHiXmHBwlwkA===
*/
这是一个比较 .NET 和 SQL 服务器的 base64 编码的示例:
using System;
using System.Data;
using System.Linq;
using System.Data.SqlClient;
namespace netcore3test
{
class File
{
public byte[] Content { get; set; }
}
class Program
{
static void Main(string[] args)
{
var maxLen = 1024 * 1024;
using var con = new SqlConnection("server=localhost;database=tempdb;integrated security=true");
con.Open();
var cmd = con.CreateCommand();
cmd.CommandText = @"
with q as (select @buf Content)
select CAST('' as XML).value('xs:base64Binary(sql:column(""Content""))', 'NVARCHAR(MAX)') base64string
from q
";
var pBuf = cmd.Parameters.Add("@buf", SqlDbType.VarBinary, -1);
var rand = new Random(0);
;
for (int len = 0; len < maxLen; len++)
{
var buf = new byte[len];
rand.NextBytes(buf);
pBuf.Value = buf;
var netBase64 = Convert.ToBase64String(buf);
var sqlBase64 = (string)cmd.ExecuteScalar();
var json = @$"{{""Content"" : ""{sqlBase64}"" }}";
var File = System.Text.Json.JsonSerializer.Deserialize<File>(json);
var sqlBuf = File.Content;
if (!buf.SequenceEqual(sqlBuf) || netBase64 != sqlBase64)
{
Console.WriteLine($"Fail {netBase64} {sqlBase64}");
}
Console.WriteLine(sqlBase64);
}
}
}
}