[英]How to insert NULL into SQL Server DATE field *from XML*
I've got some XML that I'm trying to insert into a Microsoft SQL Server database using their XML datatype functions . 我有一些XML,我试图使用他们的XML数据类型函数插入到Microsoft SQL Server数据库中。
One of the table fields is a nullable DATE
column. 其中一个表字段是可以为空的
DATE
列。 If the node is missing, then it's inserted as NULL
which is great. 如果节点丢失,则将其插入为
NULL
,这很好。 However, if the node is present but empty <LastDay/>
when running the XPath query, it interprets the value from the empty node as an empty string ''
instead of NULL
. 但是,如果节点存在但在运行XPath查询时为空
<LastDay/>
,则它将空节点中的值解释为空字符串''
而不是NULL
。 So when looking at the table results, it casts the date to 1900-01-01 by default. 因此,在查看表结果时,默认情况下会将日期转换为1900-01-01。
I would like for empty nodes to also be inserted as NULL
instead of the default empty string ''
or 1900-01-01. 我想将空节点也插入为
NULL
而不是默认的空字符串''
或1900-01-01。 How can I get it to insert NULL
instead? 我怎样才能让它插入
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)
This produces: 这会产生:
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
I am trying to achieve: 我想要实现:
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
You have to use NULLIF
function to avoid default values popping out from XML selection. 您必须使用
NULLIF
函数来避免从XML选择中弹出默认值。
Returns a null value if the two specified expressions are equal.
如果两个指定的表达式相等,则返回null值。
Your query will be changed as below: 您的查询将更改如下:
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)
For more information on NULLIF
, please check this MSDN page . 有关
NULLIF
更多信息,请查看此MSDN页面 。
Besides techspider's very good answer I'd like to show another approach: 除了techspider的非常好的答案,我想展示另一种方法:
Doing .nodes()
on Company and CROSS APPLY .nodes()
on Employee allows a cleaner XPath navigation and avoids the backward navigation you are using by ../@dmd.name
. 在Company上执行
.nodes()
和在Employee上执行CROSS APPLY .nodes()
允许更清晰的XPath导航,并避免使用../@dmd.name
进行后向导航。 In your case this is just for info probably, but good to consider: If there was a company without any Employee you would skip the whole company otherwise... (My code would skip as well due to the CROSS APPLY
, but you could use OUTER APPLY
). 在你的情况下,这可能只是为了信息,但很好的考虑:如果有一个公司没有任何员工,你会跳过整个公司,否则...(我的代码将跳过由于
CROSS APPLY
,但你可以使用OUTER APPLY
)。
And to your actual question: Using the internal cast as xs:date
will do the logic within the XQuery and should be faster... 对于你的实际问题:使用内部
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.