是否可以将xml作为字符串插入到varbinary中,它是否类似于作为blob插入?

时间:2017-08-10 19:15:04

标签: sql sql-server xml

是否可以将xml作为字符串插入到varbinary中,并且它类似于作为blob插入?例如,当我将xml作为blob插入时

import org.springframework.web.portlet.ModelAndView;

作为blob插入的文件看起来像enter image description here

当我插入相同的xml但作为字符串

declare @i int = 1
declare @file varchar(2000) = concat('K:\test\file',@i,'.xml');
declare @blob varbinary(max)
declare @sql nvarchar(max) = concat(N'select @blob = BulkColumn FROM 
OPENROWSET(BULK ''',@file,''', SINGLE_BLOB) myfile')

exec sp_executesql @sql, N'@blob varbinary(max) output', @blob = @blob 
output
select @blob 

insert tab1 values (@blob)

看起来完全不同

enter image description here

@Jacob

enter image description here

@Siyual

enter image description here

2 个答案:

答案 0 :(得分:0)

将文件存储为VARBINARY是一个非常糟糕的主意,就像从磁盘中读取文件一样。

一些背景

DECLARE @YourThirdVarbinary VARBINARY(MAX)=0xfffe3c006e006f00740065003e003c0074006f003e00;
SELECT CAST(@YourThirdVarbinary AS NVARCHAR(MAX));

前导FFFE指向带有byte order mark UTF-16小端编码文件。

以下3C00 6E00 6F00 ...清楚地表明您正在阅读 2字节编码的字符。

SQL-Server在内部使用UCS-2,并且本身无法读取每个UTF-16编码。我假设你生活在一个国家,在那里你处理许多角色,而不是普通的拉丁语 ......

但您提供的第一个示例是单字节编码的字符串:

DECLARE @YourFirstVarbinary VARBINARY(MAX)=0x3c6e6f74653E0D0A3c746f3e546f76653c2f746f3e;
SELECT CAST(@YourFirstVarbinary AS VARCHAR(MAX));

您的代码点之间缺少00显示,这是 1字节存储没有BOM,可能是某种UTF-8

UTF-8将普通拉丁语存储为单个字节,但特殊字符将占用更多字节,一个字母最多可包含4个字节。

SQL-Server会将 1字节编码的字符串视为VARCHAR扩展为ascii ,依赖于COLLATION(包括a code page)(多字节代码必定会导致错误!)

您会发现形成单词<note>的相同代码点:

DECLARE @PureCodePoints VARBINARY(MAX)=0x3c6e6f74653E;
SELECT CAST(@PureCodePoints AS VARCHAR(MAX));

作为 2字节代码(参见N VARCHAR):

DECLARE @PureCodePointsWide VARBINARY(MAX)=0x3c006e006f00740065003E00;
SELECT CAST(@PureCodePointsWide AS NVARCHAR(MAX));

明确建议

  • 将XML存储在本机类型的列中!优点:XML不会存储为您看到的文本,而是存储为层次树。这快得多!使用您的方法,您必须将VARBINARY强制转换为字符串并一遍又一遍地解析...

  • 永远不要将数据存储为VARBINARY,如果您无法确保,您知道任何情况下的编码,并且SQL-Server将能够处理此格式。

答案 1 :(得分:0)

存储XML的方式取决于对这些数据的处理方式。

  • 如果您的目标只是存储和访问文件,而不管它是否确实是XML,那么varbinaryFILESTREAM绝对没问题。
  • 如果您知道它是文本文件(包括XML),但不需要任何XML特定的操作,则可以使用varcharnvarchar
  • 如果您要进行任何类型的XML操作,xml将是合乎逻辑的选择。

根据我的经验,后者有一些警告:

  • 可能对XML进行了签名,如果要注意不要破坏它。在这种情况下,您应该考虑将XML存储为二进制文件,但要添加一个额外的XML列。

  • 如果您的XML指定的编码与应用程序提供的编码不兼容,则可能会出现诸如以下错误:

      

    XML解析:第1行,字符45,无法切换编码

    以下示例说明了这种情况:

SELECT CAST(N'<?xml version="1.0" encoding="windows-1251"?><xml></xml>' AS xml)
SELECT CAST(N'<?xml version="1.0" encoding="utf-8"?><xml></xml>' AS xml)
SELECT CAST('<?xml version="1.0" encoding="utf-16"?><xml></xml>' AS xml)

这些很好:

SELECT CAST(N'<?xml version="1.0" encoding="utf-16"?><xml></xml>' AS xml)
SELECT CAST('<?xml version="1.0" encoding="utf-8"?><xml></xml>' AS xml)
SELECT CAST('<?xml version="1.0" encoding="windows-1251"?><xml></xml>' AS xml)
SELECT CAST(N'<xml></xml>' AS xml)
SELECT CAST('<xml></xml>' AS xml)