SQL 服务器 - 带有 xml 命名空间和交叉应用的子查询
SQL Server - subquery with xmlnamespaces and cross apply
我想使用以下结果连接到其他表:
;with xmlnamespaces ('http://thatonecompany.com/rest/model' as ns1)
select id,
isnull(null, cast(substring(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from MyOldXMLTable mo
cross apply mo.x.nodes('/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'
and mo.id < 10
结果是:
+----+--------+
| id | loc_id |
+----+--------+
| 3 | 47 |
| 4 | 47 |
| 5 | 47 |
| 6 | 47 |
| 7 | 47 |
| 8 | 47 |
| 9 | 47 |
+----+--------+
我希望我能做类似的事情:
select * from (
;with xmlnamespaces ('http://thatonecompany.com/rest/model' as ns1)
select id,
isnull(null, cast(substring(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from MyOldXMLTable mo
cross apply mo.x.nodes('/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'
and mo.id < 10 ) as aa
...然后加入它,但是没有。由于 ;WITH 和交叉应用,我不断收到语法错误。有人知道我应该怎么做吗?
WITH XMLNAMESPACES 适用于整个查询(非常方便,声明一次命名空间并在查询中的任何地方使用它们)。
您还可以使用 xquery/inline 名称空间声明,它们往往过于冗长。
create table #myoldxmltable
(
id int identity(1,1) primary key clustered,
x xml
);
insert into #myoldxmltable(x)
values(N'<ns1:Entities xmlns:ns1="http://thatonecompany.com/rest/model">
<ns1:Entity>
<ns1:Attribute name="foundTheRightOne">
<ns1:Entity href="http://test123.com/abc/1234567" />
</ns1:Attribute>
</ns1:Entity>
</ns1:Entities>
');
--simple derived/as
with xmlnamespaces ('http://thatonecompany.com/rest/model' as ns1)
select *
from
(
select id,
isnull(null, cast(substring(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from #myoldxmltable mo
cross apply mo.x.nodes('/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'
and mo.id < 10
) as aa;
--join with another table
with xmlnamespaces ('http://thatonecompany.com/rest/model' as ns1)
select *
from
(
select id,
isnull(null, cast(substring(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from #myoldxmltable mo
cross apply mo.x.nodes('/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'
and mo.id < 10
) as aa
join sys.columns as o on aa.id = o.column_id and o.object_id = 3; --sql2019 , abysmal execution !!??!!
--a different flavor, xquery namespace declaration (way too verbose)
--compare this with the query using xmlnamespaces
select *
from
(
select id,
isnull(null, cast(substring(p.col.value('declare namespace ns1="http://thatonecompany.com/rest/model";(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('declare namespace ns1="http://thatonecompany.com/rest/model"; (./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from #myoldxmltable mo
cross apply mo.x.nodes('
declare namespace ns1="http://thatonecompany.com/rest/model";
/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'--no need for ns1 declaration, path just references an attribute, no ns1
and mo.id < 10
) as aa;
drop table #myoldxmltable;
我想使用以下结果连接到其他表:
;with xmlnamespaces ('http://thatonecompany.com/rest/model' as ns1)
select id,
isnull(null, cast(substring(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from MyOldXMLTable mo
cross apply mo.x.nodes('/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'
and mo.id < 10
结果是:
+----+--------+
| id | loc_id |
+----+--------+
| 3 | 47 |
| 4 | 47 |
| 5 | 47 |
| 6 | 47 |
| 7 | 47 |
| 8 | 47 |
| 9 | 47 |
+----+--------+
我希望我能做类似的事情:
select * from (
;with xmlnamespaces ('http://thatonecompany.com/rest/model' as ns1)
select id,
isnull(null, cast(substring(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from MyOldXMLTable mo
cross apply mo.x.nodes('/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'
and mo.id < 10 ) as aa
...然后加入它,但是没有。由于 ;WITH 和交叉应用,我不断收到语法错误。有人知道我应该怎么做吗?
WITH XMLNAMESPACES 适用于整个查询(非常方便,声明一次命名空间并在查询中的任何地方使用它们)。 您还可以使用 xquery/inline 名称空间声明,它们往往过于冗长。
create table #myoldxmltable
(
id int identity(1,1) primary key clustered,
x xml
);
insert into #myoldxmltable(x)
values(N'<ns1:Entities xmlns:ns1="http://thatonecompany.com/rest/model">
<ns1:Entity>
<ns1:Attribute name="foundTheRightOne">
<ns1:Entity href="http://test123.com/abc/1234567" />
</ns1:Attribute>
</ns1:Entity>
</ns1:Entities>
');
--simple derived/as
with xmlnamespaces ('http://thatonecompany.com/rest/model' as ns1)
select *
from
(
select id,
isnull(null, cast(substring(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from #myoldxmltable mo
cross apply mo.x.nodes('/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'
and mo.id < 10
) as aa;
--join with another table
with xmlnamespaces ('http://thatonecompany.com/rest/model' as ns1)
select *
from
(
select id,
isnull(null, cast(substring(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('(./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from #myoldxmltable mo
cross apply mo.x.nodes('/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'
and mo.id < 10
) as aa
join sys.columns as o on aa.id = o.column_id and o.object_id = 3; --sql2019 , abysmal execution !!??!!
--a different flavor, xquery namespace declaration (way too verbose)
--compare this with the query using xmlnamespaces
select *
from
(
select id,
isnull(null, cast(substring(p.col.value('declare namespace ns1="http://thatonecompany.com/rest/model";(./ns1:Entity/@href)[1]', 'nvarchar(max)'), 24, len(p.col.value('declare namespace ns1="http://thatonecompany.com/rest/model"; (./ns1:Entity/@href)[1]', 'nvarchar(max)'))) as integer)) loc_id
from #myoldxmltable mo
cross apply mo.x.nodes('
declare namespace ns1="http://thatonecompany.com/rest/model";
/ns1:Entities/ns1:Entity/ns1:Attribute') as p(col)
where p.col.value('@name', 'nvarchar(max)') = 'foundTheRightOne'--no need for ns1 declaration, path just references an attribute, no ns1
and mo.id < 10
) as aa;
drop table #myoldxmltable;