2013-02-21 45 views
3

我创建了一个包含两个表的新数据库来测试SQLServer 2008 XML功能。如何编写访问存储在单独的SQL Server表中的XML的XQuery?

如果我能够成功获得所需的行为,那么我将不得不创建大约50个表格,然后为新项目导入大量XML文件。

我的测试环境已经创造了这个办法:

create table Employees(
    idEmployeeFeed bigint primary key IDENTITY(1,1), 
    EmployeeFeed xml 
) 
go 

create table GeoCountries(
    CountriesFeed xml 
) 
go 

我再装在雇员表约1000 XML文件和1个文件中的地理国家表。 GeoCountries文件包含249个国家的纬度/长度质心坐标,加上国家名称和ISO 3字符的国家代码。

每个员工都有一个国家代码。我已经在另一个产品中准备好了XQuery,现在我需要根据客户端要求迁移到SQL Server。从使用XQuery获得的两个表

的样本数据:

select EmployeeFeed.query('//employee') as employee 
from Employees 
/* output: 
    <employee empID="1111" > 
     <displayName>John</displayName> 
     <country code="USA" /> 
    </employee> 
    <employee empID="2222" > 
     <displayName>Mario</displayName> 
     <country code="ITA" /> 
    </employee> 
    ... 
*/ 

select EmployeeFeed.query('//employee/country') as employee 
from Employees 
/* output: 
    <country code="USA" /> 
    <country code="ITA" /> 
    ... 
*/ 

select CountriesFeed.query('//country') 
from GeoCountries 
/* output: 
    <country> 
     <ISO3166A3>USA</ISO3166A3> 
     <ISOen_name>United States</ISOen_name> 
     <latitude>38.000</latitude> 
     <longitude>-97.000</longitude> 
    </country> 
    <country> 
     <ISO3166A3>ITA</ISO3166A3> 
     <ISOen_name>Italy</ISOen_name> 
     <latitude>42.833</latitude> 
     <longitude>12.833</longitude> 
    </country> 
    ... 
*/ 

select CountriesFeed.query('//country/ISO3166A3') 
from GeoCountries 
/* output: 
    <ISO3166A3>USA</ISO3166A3> 
    <ISO3166A3>ITA</ISO3166A3> 
    ... 
*/ 

这是我试图运行查询:

select EmployeeFeed.query(N' 
    let $ccc := //country 
    let $ttt := //employee 
    for $t in $ttt 
    return 
     <geoEmp 
     empCode="{ $t/@empID }" 
     countryCode="{ $t/country/@code }" 
     latit="{ $ccc[ISO3166A3 = $t/country/@code]/latitude/text() }" 
     longit="{ $ccc[ISO3166A3 = $t/country/@code]/longitude/text() }" 
     /> 
') as GeoEmployees 
from Employees 
/* output: 
    <geoEmp empCode="1111" countryCode="USA" latit="" longit="" /> 
    <geoEmp empCode="2222" countryCode="ITA" latit="" longit="" /> 
    ... 
*/ 

正如你可以看到,国家代码+经纬度/ long预先加载到变量$ ccc中,将其用作查找表,但是,作为另一个SQL表(GeoCountries)中的数据,它不能在与SQL表Employees相关联的当前XQuery上下文中找到。

有没有办法运行XQuery访问存储在单独的SQL表中的XML? 如果我迁移,我将有100-200类似的情况进行管理,我需要为这个问题找到一个有效的解决方案。

+1

你能告诉我们什么实际的个人EmployeesFeed和ContriesFeed XML是什么样子?现在,您只能通过Query的许多实例向我们显示重构的XML,因此不清楚单个行的外观。 – RBarryYoung 2013-02-21 14:38:37

回答

1

如何:

select e.empID as '@empCode', c.code as '@countryCode', c.lat as '@latit', c.long as '@longit' from (
    select e.emp.value('(@empID)[1]', 'int') as empID, e.emp.value('(country/@code)[1]', 'varchar(32)') as code 
    from Employees 
    cross apply EmployeeFeed.nodes('//employee') e(emp) 
) e 
inner join (
    select c.country.value('(ISO3166A3)[1]', 'varchar(32)') as code, c.country.value('(latitude)[1]', 'varchar(32)') as lat, c.country.value('(longitude)[1]', 'varchar(32)') as long 
    from GeoCountries 
    cross apply CountriesFeed.nodes('//country') c(country) 
) c on e.code = c.code 
for xml path('geoEmp'), type 
+0

谢谢穆罕默德。你的方法有效,我可以得到想要的结果。我只是担心从代码的复杂性和数量方面的开销,似乎需要从纯粹的xquery切换...基本上,我们要去一个中间的SQL数据集,然后切换回到XML与“for XML”。有没有办法使用类似于fn:doc(tablename)方法的方式在其他表中引用xml?我也想知道这种方法是否会引起一定程度的性能下降...... – MarioCannistra 2013-02-21 15:26:51

+0

如果需要,您可以创建XML索引。然而,如果你想要Xquery,我想你将不得不通过连接或可能与sqlvariable在同一地方获得xml的位 - http://msdn.microsoft.com/en-us/library/ ms188254.aspx。即使这样,你仍然需要浏览大部分的XML,但这次是在Xquery中。你可以试着用where子句来减少这个,但是你也可以把它应用到上面。 – muhmud 2013-02-21 18:42:50

+0

我有完全相同的问题,我想知道你是否确实找到了一种方法来说:“从XQuery中的其他表中引用xml数据(例如fn:doc(tablename)还是fn:collection(collectioname)?或者,可能吗?SQL Server 2014的新功能如何?提前致谢。 – Adrian 2014-03-25 09:07:44

相关问题