SQLSERVER NULL值的XML处理

1、使用for xml语句将数据库中的的数据生成xml文档时,有些值为null的列没有生成到xml文档;

如下图:

使用语句:

SELECT TOP 1 tp.ID, tp.machine_id, tp.plan_time, tp.product_num, tp.art_num,
       tp.start_time, tp.end_time, tp.arrange_main_iden
FROM DADXDB.dbo.table_plan AS tp
ORDER BY tp.plan_time DESC
FOR XML PATH('plan_rec') ,ELEMENTS

生成xml:

<plan_rec>
  <ID>18700</ID>
  <machine_id>DX-5</machine_id>
  <plan_time>2022-07-14T14:10:29</plan_time>
  <product_num>D470219A</product_num>
  <art_num>D470219A</art_num>
  <arrange_main_iden>52233</arrange_main_iden>
</plan_rec>

这里不包含start_time和end_time。

如何才能让xml中包含这两列呢?

使用下面的方法:

SELECT TOP 1 tp.ID, tp.machine_id, tp.plan_time, tp.product_num, tp.art_num,
       tp.start_time, tp.end_time, tp.arrange_main_iden
FROM DADXDB.dbo.table_plan AS tp
ORDER BY tp.plan_time DESC
FOR XML PATH('plan_rec') ,ELEMENTS XSINIL

生成的xml如下:

<plan_rec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ID>18700</ID>
  <machine_id>DX-5</machine_id>
  <plan_time>2022-07-14T14:10:29</plan_time>
  <product_num>D470219A</product_num>
  <art_num>D470219A</art_num>
  <start_time xsi:nil="true" />
  <end_time xsi:nil="true" />
  <arrange_main_iden>52233</arrange_main_iden>
</plan_rec>

请注意上面的xml中已经包含了start_time和end_time列,另外也在开始时增加了一个namespace的定义,这些就是使用xsinil后起的效果;

2、如何从xml文档中正确读出null值到sqlserver中

上面的方法说明如何将null值生成到xml中,那么在xml中的null值如何能被正确的识别处理呢?特别时对于日期类型值,默认情况读出时,null值往往被转换为1900-1-1 00:00:00,这些不是一个很好的地方;

如,下面的xml:

<plan_rec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ID>18700</ID>
  <machine_id>DX-5</machine_id>
  <plan_time>2022-07-14T14:10:29</plan_time>
  <product_num>D470219A</product_num>
  <art_num>D470219A</art_num>
  <start_time xsi:nil="true" />
  <end_time xsi:nil="true" />
  <arrange_main_iden>52233</arrange_main_iden>
</plan_rec>

(1)、使用xml的value语句:

DECLARE @tmpXml XML
SELECT @tmpXml='<plan_rec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ID>18700</ID>
  <machine_id>DX-5</machine_id>
  <plan_time>2022-07-14T14:10:29</plan_time>
  <product_num>D470219A</product_num>
  <art_num>D470219A</art_num>
  <start_time xsi:nil="true" />
  <end_time xsi:nil="true" />
  <arrange_main_iden>52233</arrange_main_iden>
</plan_rec>'

SELECT @tmpXml.value('(/plan_rec/start_time)[1]','datetime')

执行结果如下:

注意这里的datetime 没有正确的被转换成null;

DECLARE @tmpXml XML 
SELECT @tmpXml='<plan_rec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ID>18700</ID>
  <machine_id>DX-5</machine_id>
  <plan_time>2022-07-14T14:10:29</plan_time>
  <product_num>D470219A</product_num>
  <art_num>D470219A</art_num>
  <start_time xsi:nil="true" />
  <end_time xsi:nil="true" />
  <arrange_main_iden>52233</arrange_main_iden>
</plan_rec>'

SELECT @tmpXml.value('(/plan_rec/start_time[not(@xsi:nil = "true")])[1]','datetime')

注意上面代码中在xpath部分,增加了一个属性过滤条件:[not(@xsi:nil = "true")],这样会报标识为nil的元素过滤掉,所以,会正确返回null,如下:

 (2)、使用openxml语句

尝试1:


DECLARE @tmpXml VARCHAR(8000) 
SELECT @tmpXml= '<plan_rec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ID>18700</ID>
  <machine_id>DX-5</machine_id>
  <plan_time>2022-07-14T14:10:29</plan_time>
  <product_num>D470219A</product_num>
  <art_num>D470219A</art_num>
  <start_time xsi:nil="true" />
  <end_time xsi:nil="true" />
  <arrange_main_iden>52233</arrange_main_iden>
</plan_rec>'
DECLARE @hdoc INT
EXEC sp_xml_preparedocument @hdoc OUTPUT,@tmpXml
SELECT *
FROM OPENXML(@hdoc,'/plan_rec',2)
WITH(
	ID INT ,
	machine_id VARCHAR(10),
	plan_time DATETIME,
	product_num VARCHAR(10),
	art_num VARCHAR(20),
	start_time DATETIME,
	end_time DATETIME,
	arrange_main_iden INT
)

执行结果:

从执行结果中可以看到start_time和end_time没有被正确读取;

尝试2,在with列定义处,指明xpath路径采用类似value方法的属性过滤


DECLARE @tmpXml VARCHAR(8000) 
SELECT @tmpXml= '<plan_rec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ID>18700</ID>
  <machine_id>DX-5</machine_id>
  <plan_time>2022-07-14T14:10:29</plan_time>
  <product_num>D470219A</product_num>
  <art_num>D470219A</art_num>
  <start_time xsi:nil="true" />
  <end_time xsi:nil="true" />
  <arrange_main_iden>52233</arrange_main_iden>
</plan_rec>'
DECLARE @hdoc INT
EXEC sp_xml_preparedocument @hdoc OUTPUT,@tmpXml
SELECT *
FROM OPENXML(@hdoc,'/plan_rec',2)
WITH(
	ID INT ,
	machine_id VARCHAR(10),
	plan_time DATETIME,
	product_num VARCHAR(10),
	art_num VARCHAR(20),
	start_time DATETIME '/start_time[not(@xsi:nil = "true")]',
	end_time DATETIME,
	arrange_main_iden INT
)

EXEC sp_xml_removedocument @hdoc

但是这时执行,会报如下错误;

 尝试3:

在使用sp_xml_preparedocument过程时,指明命名空间,如下:

DECLARE @tmpXml VARCHAR(8000) 
SELECT @tmpXml= '<plan_rec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ID>18700</ID>
  <machine_id>DX-5</machine_id>
  <plan_time>2022-07-14T14:10:29</plan_time>
  <product_num>D470219A</product_num>
  <art_num>D470219A</art_num>
  <start_time xsi:nil="true" />
  <end_time xsi:nil="true" />
  <arrange_main_iden>52233</arrange_main_iden>
</plan_rec>'
DECLARE @hdoc INT
EXEC sp_xml_preparedocument @hdoc OUTPUT,@tmpXml,'<plan_rec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>'
SELECT *
FROM OPENXML(@hdoc,'/plan_rec',2)
WITH(
	ID INT ,
	machine_id VARCHAR(10),
	plan_time DATETIME 'plan_time[not(@xsi:nil = "true")]' ,
	product_num VARCHAR(10),
	art_num VARCHAR(20),
	start_time DATETIME '/start_time[not(@xsi:nil = "true")]',
	end_time DATETIME  '/end_time[not(@xsi:nil = "true")]',
	arrange_main_iden INT
)

EXEC sp_xml_removedocument @hdoc

执行结果如下:

这个才是理想的解析结果

3、使用select for xml查询生成xml后,直接使用value函数报错问题;

如下面语句:

SELECT 
(
	SELECT TOP 1 tp.ID, tp.machine_id, tp.plan_time, tp.product_num, tp.art_num,
	       tp.start_time, tp.end_time, tp.arrange_main_iden
	FROM DADXDB.dbo.table_plan AS tp
	ORDER BY tp.plan_time DESC
	FOR XML PATH('plan_rec') ,ELEMENTS XSINIL  
).value('(/plan_rec/start_time)[1]','datetime')

会报下图错误:

这时我们只需要对上面sql语句做如下修改就可以解决这个问题:

SELECT 
(
	SELECT TOP 1 tp.ID, tp.machine_id, tp.plan_time, tp.product_num, tp.art_num,
	       tp.start_time, tp.end_time, tp.arrange_main_iden
	FROM DADXDB.dbo.table_plan AS tp
	ORDER BY tp.plan_time DESC
	FOR XML PATH('plan_rec') ,ELEMENTS XSINIL,TYPE  
).value('(/plan_rec/start_time)[1]','datetime')

 注意:上面代码中增加了Type关键字,表示当前这个查询结果是一个xml类型,这时就不会报错了。

对于上面的内容,对于有特殊要求时可以按照上面的方式处理;,如果没有的话完全可以使用sqlserver的默认行为处理:

1、sqlserver中的null数据不会生成到xml中;

2、在使用value/openxml读取xml时,这些的对应信息也自然会是null

3、如果sqlserver中有值,那么就会出现到xml中;

4、这样后续读取时,也自然会读取到。

当然,对于一些非字符串类型,sqlserver会有一些默认值,而这些默认值往往不是我们想要的,所以简单一点,就是将所有的类就是声明成字符串类型,这样如果有null值时,会解释为空串,这样可能会更符合我们的理解习惯。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SQL Server中进行XML模糊查询可以使用XPath表达式和LIKE运算符的结合。根据引用\[1\]中的示例,可以使用以下语法进行查询: ```sql SELECT <column_name> FROM MyTable WHERE <column_name>.value('(/root/sub-tag)\[1\]', 'varchar(max)') LIKE 'StringToSearchFor' ``` 其中,`<column_name>`是要查询的列名,`MyTable`是表名,`(/root/sub-tag)\[1\]`是XPath表达式,用于指定要查询的XML节点路径,`StringToSearchFor`是要模糊匹配的字符串。 另外,根据引用\[2\]中的示例,如果要在`patient_info`表中进行模糊查询,可以使用以下语法: ```sql SELECT * FROM patient_info WHERE create_time LIKE '%' + ${searchTime} + '%' ``` 其中,`${searchTime}`是要查询的日期字符串,使用`LIKE`运算符和`%`通配符来实现模糊匹配。 请根据具体的需求选择适合的查询语法进行XML模糊查询。 #### 引用[.reference_title] - *1* [SQLSERVER XML 类型列的模糊查询](https://blog.csdn.net/weixin_34306676/article/details/94133268)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [关于在xml文件中拼接模糊查询SQL语句问题](https://blog.csdn.net/XuDream/article/details/122177326)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值