簡體   English   中英

如何從XML *向SQL Server DATE字段*中插入NULL

[英]How to insert NULL into SQL Server DATE field *from XML*

我有一些XML,我試圖使用他們的XML數據類型函數插入到Microsoft SQL Server數據庫中。

其中一個表字段是可以為空的DATE列。 如果節點丟失,則將其插入為NULL ,這很好。 但是,如果節點存在但在運行XPath查詢時為空<LastDay/> ,則它將空節點中的值解釋為空字符串''而不是NULL 因此,在查看表結果時,默認情況下會將日期轉換為1900-01-01。

我想將空節點也插入為NULL而不是默認的空字符串''或1900-01-01。 我怎樣才能讓它插入NULL呢?

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)

這會產生:

 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

我想要實現:

 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

您必須使用NULLIF函數來避免從XML選擇中彈出默認值。

如果兩個指定的表達式相等,則返回null值。

您的查詢將更改如下:

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頁面

除了techspider的非常好的答案,我想展示另一種方法:

Company上執行.nodes()和在Employee上執行CROSS APPLY .nodes()允許更清晰的XPath導航,並避免使用../@dmd.name進行后向導航。 在你的情況下,這可能只是為了信息,但很好的考慮:如果有一個公司沒有任何員工,你會跳過整個公司,否則...(我的代碼將跳過由於CROSS APPLY ,但你可以使用OUTER APPLY )。

對於你的實際問題:使用內部cast as xs:date將在XQuery中執行邏輯並且應該更快...

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM