我有一个XML格式的日志文件,我想安排自动导入SQL。我能够使用OPENROWSET和OPENXML部分导入数据,但是我无法导入一些数据,因为它在同一节点级别。具体而言,“用户”节点与“storageObject”处于同一级别,“cabinet”节点与“Client”,“Matter”等处于同一级别。
示例XML:
<ActivityLog repositoryId="ZZ-T6KQ1I1B" repositoryName="Training" startDate="2017-07-01" endDate="2017-09-18">
<activity date="2017-08-08T10:29:02" name="change access list" host="127.0.0.1">
<user id="JS" name="John Smith" memberType="I" />
<storageObject docId="4161-1264-9996" name="Hello World" size="0" fileExtension="eml">
<cabinet name="Materials">QPIRVQK</cabinet>
</storageObject>
</activity>
<activity date="2017-08-08T10:29:03" name="change access list" host="127.0.0.1">
<user id="JS" name="John Smith" memberType="I" />
<storageObject docId="4161-1264-9996" name="Screen Shot" size="0" fileExtension="jpg">
<cabinet name="Materials">QPIRVQK</cabinet>
<Client>1011</Client>
<Matter>007</Matter>
<Author>EMAIL</Author>
<DocumentType>JPG</DocumentType>
</storageObject>
</activity>
</ActivityLog>
我的T-SQL脚本:
DECLARE @x xml
SELECT @x=L
FROM OPENROWSET (BULK 'C:\Log.xml', SINGLE_BLOB) AS Log(L)
DECLARE @hdoc int
EXEC sp_xml_preparedocument @hdoc OUTPUT, @x
SELECT *
FROM OPENXML (@hdoc, 'ActivityLog/activity/storageObject/cabinet', 1)
WITH (
activitydate datetime '../../@date',
activityname nvarchar(max) '../../@name',
host nvarchar(32) '../../@host',
id nvarchar(32) '../@id',
username nvarchar(max) '../@username',
memberType nvarchar(50) '../@memberType',
docId nvarchar(50) '../@docId',
filename nvarchar(max) '../@filename',
size int '../@size',
fileExtension nvarchar(max) '../@fileExtension',
cabinetname nvarchar(max) '@cabinetname',
Client nvarchar(max) '@Client',
Matter nvarchar(max) '@Matter',
Author nvarchar(max) '@Author',
DocumentType nvarchar(max) '@DocumentType'
)
EXEC sp_xml_removedocument @hdoc
上述脚本返回除用户标记以外的所有内容:id,username(name),memberType和Client,Matter,Author和DocumentType。如果有人可以就如何导入所有活动提供建议,那将非常感激。
答案 0 :(得分:0)
我不习惯使用OPENXML
,因为我听说这是从XML文档中检索内容的老派方式。我这样做的方式是使用SQL Server支持的XML函数。具体来说,XML函数:
nodes()方法的结果是一个包含原始XML实例的逻辑副本的行集。在这些逻辑副本中,每个行实例的上下文节点都设置为使用查询表达式标识的节点之一,以便后续查询可以相对于这些上下文节点进行导航。
对XML执行XQuery并返回SQL类型的值
你会看到例如id
(<user>
属性ID)您处于错误的级别,您必须更深入。对于例如<Client>
你再次处于错误的水平,你必须回到一个水平再次上升。我没有在你的XML中找到filename属性。
DECLARE @x XML;
SET @x=N'<ActivityLog repositoryId="ZZ-T6KQ1I1B" repositoryName="Training" startDate="2017-07-01" endDate="2017-09-18">
<activity date="2017-08-08T10:29:02" name="change access list" host="127.0.0.1">
<user id="JS" name="John Smith" memberType="I" />
<storageObject docId="4161-1264-9996" name="Hello World" size="0" fileExtension="eml">
<cabinet name="Materials">QPIRVQK</cabinet>
</storageObject>
</activity>
<activity date="2017-08-08T10:29:03" name="change access list" host="127.0.0.1">
<user id="JS" name="John Smith" memberType="I" />
<storageObject docId="4161-1264-9996" name="Screen Shot" size="0" fileExtension="jpg">
<cabinet name="Materials">QPIRVQK</cabinet>
<Client>1011</Client>
<Matter>007</Matter>
<Author>EMAIL</Author>
<DocumentType>JPG</DocumentType>
</storageObject>
</activity>
</ActivityLog>';
SELECT
activitydate=n.v.value('../../@date','DATETIME'),
activityname=n.v.value('../../@name','NVARCHAR(MAX)'),
host=n.v.value('../../@name','NVARCHAR(32)'),
id=n.v.value('../../user[1]/@id','NVARCHAR(32)'),
username=n.v.value('../../user[1]/@name','NVARCHAR(MAX)'),
memberType=n.v.value('../../user[1]/@memberType','NVARCHAR(50)'),
docId=n.v.value('../@docId','NVARCHAR(50)'),
filename=n.v.value('../@filename','NVARCHAR(MAX)'),
size=n.v.value('../@size','INT'),
fileExtension=n.v.value('../@fileExtension','NVARCHAR(MAX)'),
cabinetname=n.v.value('@cabinetname','NVARCHAR(MAX)'),
Client=n.v.value('../Client[1]','NVARCHAR(MAX)'),
Matter=n.v.value('../Matter[1]','NVARCHAR(MAX)'),
Author=n.v.value('../Author[1]','NVARCHAR(MAX)'),
DocumentType=n.v.value('../DocumentType[1]','NVARCHAR(MAX)')
FROM
@x.nodes('ActivityLog/activity/storageObject/cabinet') AS n(v);