Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dotyczy:SQL Server
W środowisku XQuery można używać konstruktorów bezpośrednich i obliczanych do konstruowania struktur XML w zapytaniu.
Uwaga / Notatka
Nie ma różnicy między konstruktorami bezpośrednimi i obliczonymi .
Używanie konstruktorów bezpośrednich
W przypadku używania konstruktorów bezpośrednich podczas konstruowania kodu XML należy określić składnię przypominającą kod XML. Poniższe przykłady ilustrują konstrukcję XML przez konstruktory bezpośrednie.
Konstruowanie elementów
W przypadku używania notacji XML można tworzyć elementy. W poniższym przykładzie użyto wyrażenia konstruktora elementu bezpośredniego i utworzono <ProductModel> element. Skonstruowany element ma trzy elementy podrzędne
Węzeł tekstowy.
Dwa węzły
<Summary>elementów i<Features>.Element
<Summary>ma jeden element podrzędny węzła tekstowego, którego wartość to"Some description".Element
<Features>ma trzy elementy podrzędne węzłów,<Color>,<Weight>i<Warranty>. Każdy z tych węzłów ma jeden węzeł tekstowy podrzędny i ma odpowiednio wartościRed,25,2 years parts and labor.
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('<ProductModel ProductModelID="111">;
This is product model catalog description.
<Summary>Some description</Summary>
<Features>
<Color>Red</Color>
<Weight>25</Weight>
<Warranty>2 years parts and labor</Warranty>
</Features></ProductModel>');
Oto wynikowy kod XML:
<ProductModel ProductModelID="111">
This is product model catalog description.
<Summary>Some description</Summary>
<Features>
<Color>Red</Color>
<Weight>25</Weight>
<Warranty>2 years parts and labor</Warranty>
</Features>
</ProductModel>
Chociaż konstruowanie elementów z wyrażeń stałych, jak pokazano w tym przykładzie, jest przydatne, prawdziwa moc tej funkcji języka XQuery to możliwość konstruowania kodu XML, który dynamicznie wyodrębnia dane z bazy danych. Do określania wyrażeń zapytania można użyć nawiasów klamrowych. W wynikowym kodzie XML wyrażenie jest zastępowane jego wartością. Na przykład następujące zapytanie konstruuje <NewRoot> element z jednym elementem podrzędnym (<e>). Wartość elementu <e> jest obliczana przez określenie wyrażenia ścieżki wewnątrz nawiasów klamrowych ("{ ... }").
DECLARE @x AS XML;
SET @x = '<root>5</root>';
SELECT @x.query('<NewRoot><e> { /root } </e></NewRoot>');
Nawiasy klamrowe działają jako tokeny przełączania kontekstu i przełączają zapytanie z konstrukcji XML na ocenę zapytania. W tym przypadku wyrażenie ścieżki XQuery wewnątrz nawiasów klamrowych , jest oceniane, /roota wyniki są zastępowane.
Oto wynik:
<NewRoot>
<e>
<root>5</root>
</e>
</NewRoot>
Poniższe zapytanie jest podobne do poprzedniego. Jednak wyrażenie w nawiasach klamrowych określa data() funkcję w celu pobrania niepodzielnej wartości <root> elementu i przypisuje je do skonstruowanego elementu , <e>.
DECLARE @x AS XML;
SET @x = '<root>5</root>';
DECLARE @y AS XML;
SET @y = (SELECT @x.query('
<NewRoot>
<e> { data(/root) } </e>
</NewRoot>'));
SELECT @y;
Oto wynik:
<NewRoot>
<e>5</e>
</NewRoot>
Jeśli chcesz użyć nawiasów klamrowych jako części tekstu zamiast tokenów przełączania kontekstu, możesz je użyć jako "}}" lub "{{", jak pokazano w tym przykładzie:
DECLARE @x AS XML;
SET @x = '<root>5</root>';
DECLARE @y AS XML;
SET @y = (SELECT @x.query('
<NewRoot> Hello, I can use {{ and }} as part of my text</NewRoot>'));
SELECT @y;
Oto wynik:
<NewRoot> Hello, I can use { and } as part of my text</NewRoot>
Poniższe zapytanie to kolejny przykład konstruowania elementów przy użyciu konstruktora bezpośredniego elementu. Ponadto wartość <FirstLocation> elementu jest uzyskiwana przez wykonanie wyrażenia w nawiasach klamrowych. Wyrażenie zapytania zwraca kroki produkcji w pierwszej lokalizacji centrum roboczego z kolumny Instrukcje tabeli Production.ProductModel.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
<FirstLocation>
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Oto wynik:
<FirstLocation>
<AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
Insert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.
</AWMI:step>
<AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
Attach <AWMI:tool>Trim Jig TJ-26</AWMI:tool> to the upper and lower right corners of the aluminum sheet.
</AWMI:step>
...
</FirstLocation>
Zawartość elementu w konstrukcji XML
Poniższy przykład ilustruje zachowanie wyrażeń w konstruowaniu zawartości elementu przy użyciu konstruktora bezpośredniego elementu. W poniższym przykładzie konstruktor elementu bezpośredniego określa jedno wyrażenie. Dla tego wyrażenia jeden węzeł tekstowy jest tworzony w wynikowym pliku XML.
DECLARE @x AS XML;
SET @x = '
<root>
<step>This is step 1</step>
<step>This is step 2</step>
<step>This is step 3</step>
</root>';
SELECT @x.query('
<result>
{ for $i in /root[1]/step
return string($i)
}
</result>');
Sekwencja wartości niepodzielnych wynikająca z obliczania wyrażenia jest dodawana do węzła tekstowego z spacją dodaną między sąsiednimi wartościami niepodzielnych, jak pokazano w wyniku. Skonstruowany element ma jedno elementy podrzędne. Jest to węzeł tekstowy zawierający wartość wyświetlaną w wyniku.
<result>This is step 1 This is step 2 This is step 3</result>
Zamiast jednego wyrażenia, jeśli określisz trzy oddzielne wyrażenia generujące trzy węzły tekstowe, sąsiadujące węzły tekstowe zostaną scalone z jednym węzłem tekstowym przez połączenie w wynikowym pliku XML.
DECLARE @x AS XML;
SET @x = '
<root>
<step>This is step 1</step>
<step>This is step 2</step>
<step>This is step 3</step>
</root>';
SELECT @x.query('
<result>
{ string(/root[1]/step[1]) }
{ string(/root[1]/step[2]) }
{ string(/root[1]/step[3]) }
</result>');
Skonstruowany węzeł elementu ma jeden element podrzędny. Jest to węzeł tekstowy zawierający wartość wyświetlaną w wyniku.
<result>This is step 1This is step 2This is step 3</result>
Konstruowanie atrybutów
Podczas konstruowania elementów przy użyciu konstruktora bezpośredniego elementu można również określić atrybuty elementu przy użyciu składni przypominającej kod XML, jak pokazano w tym przykładzie:
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('<ProductModel ProductModelID="111">;
This is product model catalog description.
<Summary>Some description</Summary>
</ProductModel>');
Oto wynikowy kod XML:
<ProductModel ProductModelID="111">
This is product model catalog description.
<Summary>Some description</Summary>
</ProductModel>
Skonstruowany element <ProductModel> ma atrybut ProductModelID i następujące węzły podrzędne:
Węzeł tekstowy,
This is product model catalog description.Węzeł elementu ,
<Summary>. Ten węzeł ma jeden węzeł tekstowy podrzędny.Some description
Podczas konstruowania atrybutu można określić jego wartość za pomocą wyrażenia w nawiasach klamrowych. W takim przypadku wynik wyrażenia jest zwracany jako wartość atrybutu.
W poniższym przykładzie data() funkcja nie jest ściśle wymagana. Ponieważ przypisujesz wartość wyrażenia do atrybutu, data() jest niejawnie stosowany do pobierania wartości typizowanej określonego wyrażenia.
DECLARE @x AS XML;
SET @x = '<root>5</root>';
DECLARE @y AS XML;
SET @y = (SELECT @x.query('<NewRoot attr="{ data(/root) }" ></NewRoot>'));
SELECT @y;
Oto wynik:
<NewRoot attr="5" />
Poniżej znajduje się kolejny przykład, w którym wyrażenia są określone dla konstrukcji atrybutu LocationID i SetupHrs. Te wyrażenia są oceniane względem kodu XML w kolumnie Instrukcja. Typizowane wartości wyrażenia są przypisywane do atrybutów.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
<FirstLocation
LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Oto częściowy wynik:
<FirstLocation LocationID="10" SetupHours="0.5" >
<AWMI:step ...
</AWMI:step>
...
</FirstLocation>
Ograniczenia implementacji
Są to ograniczenia:
Wyrażenia atrybutów z wieloma lub mieszanymi (ciągami i wyrażeniem XQuery) nie są obsługiwane. Na przykład, jak pokazano w poniższym zapytaniu, skonstruujesz kod XML, gdzie
Itemjest stałą, a wartość5jest uzyskiwana przez ocenę wyrażenia zapytania:<a attr="Item 5" />Następujące zapytanie zwraca błąd, ponieważ łączysz ciąg stały z wyrażeniem ({/x}) i nie jest to obsługiwane:
DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="Item {/x}"/>');W takim przypadku masz następujące opcje:
Formuj wartość atrybutu przez łączenie dwóch wartości niepodzielnych. Te wartości niepodzielne są serializowane do wartości atrybutu z spacją między wartościami niepodzielnych:
SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');Oto wynik:
<a attr="Item 5" />Użyj funkcji concat , aby połączyć dwa argumenty ciągu z wynikową wartością atrybutu:
SELECT @x.query('<a attr="{concat(''Item'', /x[1])}"/>');W tym przypadku nie ma miejsca dodanego między dwiema wartościami ciągu. Jeśli chcesz umieścić spację między dwiema wartościami, musisz ją jawnie podać.
Oto wynik:
<a attr="Item5" />
Wiele wyrażeń jako wartość atrybutu nie jest obsługiwanych. Na przykład następujące zapytanie zwraca błąd:
DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="{/x}{/x}"/>');Sekwencje heterogeniczne nie są obsługiwane. Każda próba przypisania sekwencji heterogenicznej jako wartości atrybutu zwraca błąd, jak pokazano w poniższym przykładzie. W tym przykładzie sekwencja heterogeniczna ciąg "Item" i element
<x>są określane jako wartość atrybutu:DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="{''Item'', /x }" />');Jeśli zastosujesz
data()funkcję, zapytanie będzie działać, ponieważ pobiera niepodzielna wartość wyrażenia ,/xktóra jest połączona z ciągiem. Poniżej znajduje się sekwencja wartości niepodzielnych:SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');Oto wynik:
<a attr="Item 5" />Kolejność węzłów atrybutów jest wymuszana podczas serializacji, a nie podczas sprawdzania typów statycznych. Na przykład następujące zapytanie kończy się niepowodzeniem, ponieważ próbuje dodać atrybut po węźle niebędącym atrybutem.
SELECT CONVERT (XML, '').query(' element x { attribute att { "pass" }, element y { "Element text" }, attribute att2 { "fail" } } '); GOPoprzednie zapytanie zwraca następujący błąd:
XML well-formedness check: Attribute cannot appear outside of element declaration. Rewrite your XQuery so it returns well-formed XML.
Dodawanie przestrzeni nazw
Podczas konstruowania kodu XML przy użyciu konstruktorów bezpośrednich nazwy skonstruowanych elementów i atrybutów można zakwalifikować przy użyciu prefiksu przestrzeni nazw. Prefiks można powiązać z przestrzenią nazw w następujący sposób:
- Za pomocą atrybutu deklaracji przestrzeni nazw.
- Przy użyciu klauzuli
WITH XMLNAMESPACES. - W prologu XQuery.
Dodawanie przestrzeni nazw za pomocą atrybutu deklaracji przestrzeni nazw
W poniższym przykładzie użyto atrybutu deklaracji przestrzeni nazw w konstrukcji elementu <a> w celu zadeklarowania domyślnej przestrzeni nazw. Konstrukcja elementu <b> podrzędnego cofa deklarację domyślnej przestrzeni nazw zadeklarowanej w elemecie nadrzędnym.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<a xmlns="a">
<b xmlns=""/>
</a>');
Oto wynik:
<a xmlns="a">
<b xmlns="" />
</a>
Prefiks można przypisać do przestrzeni nazw. Prefiks jest określony w konstrukcji elementu <a>.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<x:a xmlns:x="a">
<b/>
</x:a>');
Oto wynik:
<x:a xmlns:x="a">
<b />
</x:a>
Możesz cofnąć deklarowanie domyślnej przestrzeni nazw w konstrukcji XML, ale nie można deklarować prefiksu przestrzeni nazw. Poniższe zapytanie zwraca błąd, ponieważ nie można cofnąć deklarowania prefiksu określonego w konstrukcji elementu <b>.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<x:a xmlns:x="a">
<b xmlns:x=""/>
</x:a>');
Nowo skonstruowana przestrzeń nazw jest dostępna do użycia wewnątrz zapytania. Na przykład następujące zapytanie deklaruje przestrzeń nazw w konstruowaniu elementu <FirstLocation>, i określa prefiks w wyrażeniach wartości atrybutów LocationID i SetupHrs.
SELECT Instructions.query('
<FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Utworzenie nowego prefiksu przestrzeni nazw w ten sposób zastępuje wszelkie istniejące deklaracje przestrzeni nazw dla tego prefiksu. Na przykład deklaracja przestrzeni nazw , AWMI="https://someURI"w prologu zapytania jest zastępowana przez deklarację przestrzeni nazw w elemecie <FirstLocation> .
SELECT Instructions.query('
declare namespace AWMI="https://someURI";
<FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Dodawanie przestrzeni nazw przy użyciu prologu
W tym przykładzie pokazano, jak można dodawać przestrzenie nazw do skonstruowanego kodu XML. Domyślna przestrzeń nazw jest zadeklarowana w prologu zapytań.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
declare default element namespace "a";
<a><b xmlns=""/></a>');
W konstrukcji elementu <b>atrybut deklaracji przestrzeni nazw jest określony z pustym ciągiem jako jego wartością. Spowoduje to anulowanie deklarowania domyślnej przestrzeni nazw zadeklarowanej w obiekcie nadrzędnym.
Oto wynik:
<a xmlns="a">
<b xmlns="" />
</a>
Obsługa konstrukcji XML i białych znaków
Zawartość elementu w konstrukcji XML może zawierać znaki odstępu. Te znaki są obsługiwane w następujący sposób:
Znaki odstępu w identyfikatorach URI przestrzeni nazw są traktowane jako typ
anyURIXSD. W szczególności jest to sposób ich obsługi:- Wszelkie znaki odstępu na początku i na końcu są przycinane.
- Wewnętrzne wartości znaków odstępu są zwinięte w jedną spację
Znaki kanału wiersza wewnątrz zawartości atrybutu są zastępowane spacjami. Wszystkie inne znaki odstępu pozostają w miarę ich umieszczenia.
Białe znaki wewnątrz elementów są zachowywane.
W poniższym przykładzie pokazano obsługę odstępów w konstrukcji XML:
-- line feed is replaced by space.
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('
declare namespace myNS=" https://
abc/
xyz
";
<test attr=" my
test attr
value " >
<a>
This is a
test
</a>
</test>
') AS XML_Result;
Oto wynik:
-- result
<test attr="<test attr=" my test attr value "><a>
This is a
test
</a></test>
"><a>
This is a
test
</a></test>
Inne bezpośrednie konstruktory XML
Konstruktory do przetwarzania instrukcji i komentarzy XML używają tej samej składni co odpowiadająca składnia konstrukcji XML. Obsługiwane są również obliczone konstruktory dla węzłów tekstowych, ale są używane głównie do XML DML konstruowania węzłów tekstowych.
Uwaga / Notatka
Aby zapoznać się z przykładem użycia jawnego konstruktora węzła tekstowego, zobacz konkretny przykład w pliku insert (XML DML).
W poniższym zapytaniu skonstruowany kod XML zawiera element, dwa atrybuty, komentarz i instrukcję przetwarzania. Przecinek jest używany przed elementem <FirstLocation>, ponieważ tworzona jest sekwencja.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
<?myProcessingInstr abc="value" ?>,
<FirstLocation
WorkCtrID = "{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
<!-- some comment -->
<?myPI some processing instructions ?>
{ (/AWMI:root/AWMI:Location[1]/AWMI:step) }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Oto częściowy wynik:
<?myProcessingInstr abc="value" ?>
<FirstLocation WorkCtrID="10" SetupHrs="0.5">
<!-- some comment -->
<?myPI some processing instructions ?>
<AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">I
nsert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.
</AWMI:step>
...
</FirstLocation>
Korzystanie z konstruktorów obliczanych
W takim przypadku należy określić słowa kluczowe identyfikujące typ węzła, który chcesz skonstruować. Obsługiwane są tylko następujące słowa kluczowe:
- element
- atrybut
- SMS
W przypadku węzłów elementów i atrybutów te słowa kluczowe są następujące po nazwie węzła, a także przez wyrażenie ujęte w nawiasy klamrowe, które generuje zawartość dla tego węzła. W poniższym przykładzie skonstruujesz ten kod XML:
<root>
<ProductModel PID="5">Some text <summary>Some Summary</summary></ProductModel>
</root>
Oto zapytanie, które używa obliczonych konstruktorów, generuje kod XML:
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('element root
{
element ProductModel
{
attribute PID { 5 },
text{"Some text "},
element summary { "Some Summary" }
}
} ');
Wyrażenie, które generuje zawartość węzła, może określać wyrażenie zapytania.
DECLARE @x AS XML;
SET @x = '<a attr="5"><b>some summary</b></a>';
SELECT @x.query('element root
{
element ProductModel
{
attribute PID { /a/@attr },
text{"Some text "},
element summary { /a/b }
}
} ');
Obliczone konstruktory elementów i atrybutów, zgodnie ze specyfikacją XQuery, umożliwiają obliczanie nazw węzłów. W przypadku używania konstruktorów bezpośrednich w programie SQL Server nazwy węzłów, takie jak element i atrybut, muszą być określone jako literały stałe. W związku z tym nie ma różnicy w konstruktorach bezpośrednich i obliczonych konstruktorach dla elementów i atrybutów.
W poniższym przykładzie zawartość skonstruowanych węzłów jest uzyskiwana z instrukcji produkcji XML przechowywanych w kolumnie Instrukcje typu danych XML w tabeli ProductModel.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
element FirstLocation
{
attribute LocationID { (/AWMI:root/AWMI:Location[1]/@LocationID)[1] },
element AllTheSteps { /AWMI:root/AWMI:Location[1]/AWMI:step }
}
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Oto częściowy wynik:
<FirstLocation LocationID="10">
<AllTheSteps>
<AWMI:step> ... </AWMI:step>
<AWMI:step> ... </AWMI:step>
...
</AllTheSteps>
</FirstLocation>
Inne ograniczenia implementacji
Konstruktory atrybutów obliczeniowych nie mogą służyć do deklarowania nowej przestrzeni nazw. Ponadto następujące obliczone konstruktory nie są obsługiwane w programie SQL Server:
- Obliczone konstruktory węzłów dokumentu
- Obliczane konstruktory instrukcji przetwarzania
- Obliczone konstruktory komentarzy