首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从XML*将NULL插入Server日期字段*

如何从XML*将NULL插入Server日期字段*
EN

Stack Overflow用户
提问于 2016-08-17 16:13:10
回答 2查看 3.4K关注 0票数 6

我有一些XML,我正在尝试使用它们的XML数据类型函数插入Microsoft数据库中。

表字段之一是一个可空的DATE列。如果节点缺失,则将其插入为NULL,这是很好的。但是,如果节点在运行<LastDay/>查询时是空的,那么它会将空节点的值解释为NULL。因此,在查看表结果时,默认情况下它将日期转换为1900-01-01。

我希望空节点也被插入为NULL,而不是默认的空字符串''或1900-01-01。如何才能让它插入NULL呢?

代码语言:javascript
复制
CREATE TABLE myxml 
(
    "id" INT,
    "name" NVARCHAR(100),
    "company" NVARCHAR(100),
    "lastday" DATE
);

DECLARE @xml XML =
'<?xml version="1.0" encoding="UTF-8"?>
<Data xmlns="http://example.com" xmlns:dmd="http://example.com/data-metadata">
    <Company dmd:name="Adventure Works Ltd.">
        <Employee id="1">
            <Name>John Doe</Name>
            <LastDay>2016-08-01</LastDay>
        </Employee>
        <Employee id="2">
            <Name>Jane Doe</Name>
        </Employee>
    </Company>
    <Company dmd:name="StackUnderflow">
        <Employee id="3">
            <Name>Jeff Puckett</Name>
            <LastDay/>
        </Employee>
        <Employee id="4">
            <Name>Ill Gates</Name>
        </Employee>
    </Company>
</Data>';    

WITH XMLNAMESPACES (DEFAULT 'http://example.com', 'http://example.com/data-metadata' as dmd)
INSERT INTO myxml (id,name,company,lastday)
SELECT 
    t.c.value('@id',         'INT' ),
    t.c.value('Name[1]',     'VARCHAR(100)' ),
    t.c.value('../@dmd:name','VARCHAR(100)' ),
    t.c.value('LastDay[1]',  'DATE' )
FROM @xml.nodes('/Data/Company/Employee') t(c)

这就产生了:

代码语言:javascript
复制
 id  name         company              lastday
 ------------------------------------------------
 1   John Doe     Adventure Works Ltd. 2016-08-01
 2   Jane Doe     Adventure Works Ltd. NULL
 3   Jeff Puckett StackUnderflow       1900-01-01
 4   Ill Gates    StackUnderflow       NULL

我正在努力实现:

代码语言:javascript
复制
 id  name         company              lastday
 ------------------------------------------------
 1   John Doe     Adventure Works Ltd. 2016-08-01
 2   Jane Doe     Adventure Works Ltd. NULL
 3   Jeff Puckett StackUnderflow       NULL
 4   Ill Gates    StackUnderflow       NULL
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-08-17 16:17:46

您必须使用NULLIF函数来避免从XML选择中弹出默认值。

如果两个指定的表达式相等,则返回空值。

您的查询将更改如下:

代码语言:javascript
复制
SELECT 
    t.c.value('@id',         'INT' ),
    t.c.value('Name[1]','VARCHAR(100)' ),
    t.c.value('../@dmd:name',    'VARCHAR(100)' ),
    NULLIF(t.c.value('LastDay[1]',  'DATE' ),'')
FROM @xml.nodes('/Data/Company/Employee') t(c)

有关NULLIF的更多信息,请查看此MSDN页面

票数 8
EN

Stack Overflow用户

发布于 2016-08-18 10:03:36

除了技术蜘蛛的很好的答案,我还想展示另一种方法:

在公司上执行.nodes(),对员工执行CROSS APPLY .nodes()操作,可以获得更干净的XPath导航,并避免了../@dmd.name正在使用的反向导航。在你的情况下,这可能只是为了信息,但很好的考虑:如果有一个公司没有任何员工,你会跳过整个公司,否则.(由于CROSS APPLY,我的代码也会跳过,但您可以使用OUTER APPLY)。

对于您的实际问题:使用内部cast as xs:date将在XQuery中执行逻辑,并且应该更快.

代码语言:javascript
复制
WITH XMLNAMESPACES (DEFAULT 'http://example.com', 'http://example.com/data-metadata' as dmd)
INSERT INTO myxml (id,name,company,lastday)
SELECT 
    e.value('@id',          'INT' ),
    e.value('Name[1]',      'VARCHAR(100)' ),
    c.value('@dmd:name',    'VARCHAR(100)' ),
    e.value('let $x:=LastDay[1] return $x cast as xs:date?','DATE' )
FROM @xml.nodes('/Data/Company') AS A(c) 
CROSS APPLY c.nodes('Employee') AS B(e)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39001586

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档