Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O Microsoft SQL oferece um tipo de dado nativo xml com capacidades de processamento do lado do servidor:
- XQuery para consultar conteúdo XML.
- Métodos XML (
value(),query(),exist(),nodes(),modify()) para extração e modificação. - Validação opcional de esquema XML.
- Índices XML para desempenho.
O driver mssql-python envia e recebe dados XML como strings. Todo processamento XML (XQuery, métodos XML, validação de esquema) é executado do lado Microsoft SQL. Use bibliotecas xml.etree.ElementTree de Python ou similares para análise sintática XML do lado do cliente.
Quando usar XML vs JSON: Use XML quando precisar de validação de esquema, suporte a namespace ou conteúdo misto (texto entrelaçado com elementos). Use o JSON (com colunas nvarchar e as funções JSON do Microsoft SQL) quando seus dados forem orientados a pares chave-valor, consumidos por APIs da web ou não precisarem de imposição de esquema. A maioria das novas aplicações prefere JSON, a menos que os dados sejam inerentemente estruturados em documentos.
Inserir dados XML
Passe XML como uma string do Python; o driver a envia para o tipo de coluna nativo xml do Microsoft SQL.
Inserir como texto
Insira diretamente conteúdo XML como uma string em uma coluna XML usando consultas parametrizadas.
import mssql_python
from xml.etree import ElementTree as ET
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes"
)
cursor = conn.cursor()
# Create temp table for XML storage
cursor.execute("CREATE TABLE #XMLOrders (OrderID INT IDENTITY(1,1) PRIMARY KEY, OrderXML XML)")
# Insert XML as string
xml_data = """
<Order OrderID="1001">
<Customer Name="John Doe" Email="john@example.com"/>
<Items>
<Item ProductID="A1" Quantity="2" Price="29.99"/>
<Item ProductID="B2" Quantity="1" Price="49.99"/>
</Items>
</Order>
"""
cursor.execute("""
INSERT INTO #XMLOrders (OrderXML) VALUES (%(xml)s)
""", {"xml": xml_data})
conn.commit()
Construir XML com ElementTree
Construa documentos XML programaticamente usando a biblioteca ElementTree do Python e depois converta para uma string para inserção.
from xml.etree import ElementTree as ET
# Build XML document
order = ET.Element("Order", OrderID="1002")
customer = ET.SubElement(order, "Customer", Name="Jane Smith", Email="jane@example.com")
items = ET.SubElement(order, "Items")
ET.SubElement(items, "Item", ProductID="C3", Quantity="3", Price="19.99")
ET.SubElement(items, "Item", ProductID="D4", Quantity="2", Price="39.99")
# Convert to string
xml_string = ET.tostring(order, encoding="unicode")
cursor.execute("""
INSERT INTO #XMLOrders (OrderXML) VALUES (%(xml)s)
""", {"xml": xml_string})
conn.commit()
Valide XML antes de inserir
Valide a sintaxe XML no servidor usando o TRY/CATCH e o casting de tipos XML do SQL para rejeitar documentos malformados antes do armazenamento.
# Validate XML with TRY/CATCH
cursor.execute("""
BEGIN TRY
DECLARE @xml XML = CAST(%(xml)s AS XML);
SELECT @xml.value('(/Order/@OrderID)[1]', 'INT') AS Validated;
END TRY
BEGIN CATCH
THROW;
END CATCH
""", {"xml": xml_data})
Consultar dados XML
Use métodos XML no servidor para extrair valores específicos sem buscar documentos completos para o cliente.
Método XML value()
Extraia valores ou atributos escalares únicos do XML usando o value() método com expressões XPath.
Extraia valores escalares do XML:
cursor.execute("""
SELECT
OrderID,
OrderXML.value('(/Order/@OrderID)[1]', 'INT') AS XmlOrderID,
OrderXML.value('(/Order/Customer/@Name)[1]', 'NVARCHAR(100)') AS CustomerName,
OrderXML.value('(/Order/Customer/@Email)[1]', 'NVARCHAR(100)') AS Email
FROM #XMLOrders
""")
for row in cursor:
print(f"Order {row.XmlOrderID}: {row.CustomerName} ({row.Email})")
Método XML de consulta()
Retorne fragmentos de XML (não valores escalares) do documento usando expressões XPath.
Extrair fragmentos XML:
cursor.execute("""
SELECT
OrderID,
OrderXML.query('/Order/Items') AS ItemsXML
FROM #XMLOrders
WHERE OrderID = %(id)s
""", {"id": 1})
row = cursor.fetchone()
# row.ItemsXML is an XML string
items_xml = row.ItemsXML
print(items_xml)
Método XML exist()
Teste se uma expressão XPath corresponde a algum nó no documento, retornando 1 para verdadeiro e 0 para falso.
Verifique se o XPath corresponde:
cursor.execute("""
SELECT OrderID, OrderXML
FROM #XMLOrders
WHERE OrderXML.exist('/Order/Items/Item[@ProductID="A1"]') = 1
""")
for row in cursor:
print(f"Order {row.OrderID} contains product A1")
Método nodes() do XML (decomposição em linhas)
Converta elementos XML aninhados em um conjunto de linhas relacional usando o operador CROSS APPLY e o método nodes().
Converter XML para formato relacional:
cursor.execute("""
SELECT
o.OrderID,
Items.Item.value('@ProductID', 'VARCHAR(10)') AS ProductID,
Items.Item.value('@Quantity', 'INT') AS Quantity,
Items.Item.value('@Price', 'DECIMAL(10,2)') AS Price
FROM #XMLOrders o
CROSS APPLY o.OrderXML.nodes('/Order/Items/Item') AS Items(Item)
WHERE o.OrderID = %(id)s
""", {"id": 1})
for row in cursor:
print(f"Product {row.ProductID}: {row.Quantity} x ${row.Price}")
Modificar dados XML
Use XML.modify() com expressões DML XQuery para atualizar o conteúdo XML no local.
XML modify() usando insert
Adicione novos elementos a um documento XML usando o método modify() com a operação insert do XQuery.
cursor.execute("""
UPDATE #XMLOrders
SET OrderXML.modify('
insert <Item ProductID="E5" Quantity="1" Price="59.99"/>
into (/Order/Items)[1]
')
WHERE OrderID = %(id)s
""", {"id": 1})
conn.commit()
XML modify() com exclusão
Remova elementos ou nós de um documento XML usando o método modify() com a operação delete do XQuery.
cursor.execute("""
UPDATE #XMLOrders
SET OrderXML.modify('
delete /Order/Items/Item[@ProductID="A1"]
')
WHERE OrderID = %(id)s
""", {"id": 1})
conn.commit()
XML modify() com substituir
Atualize valores de atributos ou o texto de um elemento em um documento XML usando o método modify() com a operação replace value of do XQuery.
cursor.execute("""
UPDATE #XMLOrders
SET OrderXML.modify('
replace value of (/Order/Items/Item[@ProductID="B2"]/@Price)[1]
with 54.99
')
WHERE OrderID = %(id)s
""", {"id": 1})
conn.commit()
Consultas com FOR XML
Anexe FOR XML a qualquer consulta para retornar os resultados como uma única string XML.
FOR XML RAW
Gere XML onde cada linha se torna um elemento simples com colunas como atributos.
cursor.execute("""
SELECT ProductID, Name, ListPrice
FROM Production.Product
WHERE ProductSubcategoryID = %(cat)s
FOR XML RAW('Product'), ROOT('Products')
""", {"cat": 1})
xml_result = cursor.fetchval()
print(xml_result)
# <Products><Product ProductID="1" Name="..." ListPrice="..."/></Products>
PARA XML AUTO
Gerar XML com estrutura aninhada que automaticamente reflita a hierarquia de junção na sua consulta.
cursor.execute("""
SELECT sc.Name AS SubcategoryName, p.Name AS ProductName, p.ListPrice
FROM Production.ProductSubcategory sc
JOIN Production.Product p ON sc.ProductSubcategoryID = p.ProductSubcategoryID
WHERE sc.ProductSubcategoryID = %(cat)s
FOR XML AUTO, ROOT('Catalog')
""", {"cat": 1})
xml_result = cursor.fetchval()
# Nested XML structure based on join hierarchy
PARA CAMINHO XML
Construa estruturas XML personalizadas usando aliases explícitos de coluna e subconsultas para controlar o aninhamento e os nomes dos elementos.
Maior controle sobre a estrutura XML:
cursor.execute("""
SELECT
sc.ProductSubcategoryID AS '@ID',
sc.Name AS 'Name',
(
SELECT p.ProductID AS '@ID',
p.Name AS 'Name',
p.ListPrice AS 'Price'
FROM Production.Product p
WHERE p.ProductSubcategoryID = sc.ProductSubcategoryID
FOR XML PATH('Product'), TYPE
) AS 'Products'
FROM Production.ProductSubcategory sc
WHERE sc.ProductSubcategoryID = %(cat)s
FOR XML PATH('Subcategory'), ROOT('Catalog')
""", {"cat": 1})
xml_result = cursor.fetchval()
Análise XML em Python
Recupere XML como uma string e analise com xml.etree.ElementTree ou uma biblioteca compatível.
Analisar resultados de consultas com ElementTree
Busque XML do banco de dados e o analise em uma árvore de objetos Python usando ElementTree, acessando elementos e atributos via DOM.
from xml.etree import ElementTree as ET
cursor.execute("""
SELECT CatalogDescription FROM Production.ProductModel
WHERE CatalogDescription IS NOT NULL AND ProductModelID = 19
""")
row = cursor.fetchone()
root = ET.fromstring(row.CatalogDescription)
# Navigate XML structure using namespace
ns = {'pd': 'http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription'}
summary = root.find('.//pd:Summary', ns)
if summary is not None:
# Get all text content
text = ''.join(summary.itertext()).strip()
print(f"Summary: {text[:100]}")
Converter XML em dicionário
Transforme uma estrutura de árvore XML em um dicionário Python aninhado para facilitar o acesso programático a dados aninhados.
def xml_to_dict(element):
"""Convert XML element to dictionary."""
result = {}
# Add attributes
if element.attrib:
result['@attributes'] = element.attrib
# Add children
children = list(element)
if children:
child_dict = {}
for child in children:
child_result = xml_to_dict(child)
if child.tag in child_dict:
# Convert to list if multiple same-named children
if not isinstance(child_dict[child.tag], list):
child_dict[child.tag] = [child_dict[child.tag]]
child_dict[child.tag].append(child_result)
else:
child_dict[child.tag] = child_result
result.update(child_dict)
# Add text content
if element.text and element.text.strip():
result['#text'] = element.text.strip()
return result
# Usage
cursor.execute("""
SELECT CatalogDescription FROM Production.ProductModel
WHERE CatalogDescription IS NOT NULL AND ProductModelID = 19
""")
xml_string = cursor.fetchval()
root = ET.fromstring(xml_string)
data = xml_to_dict(root)
Lidar com documentos XML grandes
O Microsoft SQL pode dividir resultados grandes FOR XML em várias linhas; concatene as partes antes de analisá-las.
Buscar XML em blocos
Quando FOR XML retorna grandes conjuntos de resultados, o Microsoft SQL pode dividir o XML em várias linhas; combinar todas as partes em um único documento.
# FOR XML might split large results across rows
cursor.execute("""
SELECT * FROM LargeTable FOR XML RAW
""")
xml_parts = []
for row in cursor:
xml_parts.append(row[0])
full_xml = "".join(xml_parts)
Análise sintática XML em fluxo
Para documentos XML muito grandes, use análise sintática iterativa para processar elementos um de cada vez, sem carregar toda a árvore na memória.
from xml.etree import ElementTree as ET
import io
cursor.execute("""
SELECT Instructions FROM Production.ProductModel
WHERE Instructions IS NOT NULL AND ProductModelID = 7
""")
xml_string = cursor.fetchval()
# Use iterparse for memory-efficient parsing
xml_stream = io.StringIO(xml_string)
for event, elem in ET.iterparse(xml_stream, events=['end']):
if elem.tag.endswith('step'):
# Process step element
text = ''.join(elem.itertext()).strip()
if text:
print(f"Step: {text[:60]}")
# Free memory
elem.clear()
índices XML
Crie índices no Microsoft SQL para consultas XML mais rápidas:
-- Primary XML index (assumes a table with an XML column)
CREATE PRIMARY XML INDEX PIX_XMLOrders_OrderXML
ON #XMLOrders(OrderXML);
-- Secondary indexes for specific access patterns
CREATE XML INDEX SIX_XMLOrders_Path
ON #XMLOrders(OrderXML)
USING XML INDEX PIX_XMLOrders_OrderXML
FOR PATH;
CREATE XML INDEX SIX_XMLOrders_Value
ON #XMLOrders(OrderXML)
USING XML INDEX PIX_XMLOrders_OrderXML
FOR VALUE;
Trabalho com namespaces
Declare prefixos de namespace embutidos em expressões XQuery usando a sintaxe declare namespace.
Consultar XML com espaços de nomes
Adicione declarações de namespace às suas expressões XPath para combinar elementos em um namespace específico.
xml_with_ns = """
<Order xmlns="http://example.com/orders"
xmlns:c="http://example.com/customer">
<c:Customer Name="John Doe"/>
<Items>
<Item ProductID="A1"/>
</Items>
</Order>
"""
cursor.execute("""
SELECT OrderXML.value('
declare namespace o="http://example.com/orders";
declare namespace c="http://example.com/customer";
(/o:Order/c:Customer/@Name)[1]
', 'NVARCHAR(100)') AS CustomerName
FROM #XMLOrders
WHERE OrderID = %(id)s
""", {"id": 1})
Analisar XML com namespace em Python
Ao processar XML com namespaces em Python, declare os mapeamentos de namespace nas chamadas find() e em outras chamadas de acesso a elementos.
from xml.etree import ElementTree as ET
cursor.execute("""
SELECT TOP 1
(SELECT SalesOrderID AS [@OrderID],
TotalDue AS [@Total],
CustomerID AS [Customer/@ID]
FROM Sales.SalesOrderHeader
WHERE SalesOrderID = 43659
FOR XML PATH('Order'))
""")
xml_string = cursor.fetchval()
root = ET.fromstring(xml_string)
order_id = root.get('OrderID')
total = root.get('Total')
print(f"Order {order_id}: ${total}")
Práticas recomendadas
Aplique essas diretrizes para trabalhar com dados XML de forma eficiente.
Escolha XML versus JSON
Decida se usa o tipo nativo xml do Microsoft SQL ou armazena JSON nvarchar com base na sua estrutura de dados e necessidades de processamento:
Essa comparação ajuda você a decidir se deve usar o tipo do xml Microsoft SQL ou armazenar JSON emnvarchar:
| Característica | XML | JSON |
|---|---|---|
| Validação do esquema | Suporte nativo | Sem suporte nativo |
| Namespaces | Suporte completo | Sem suporte |
| Atributos | Supported | Nenhum equivalente direto |
| Conteúdo misto | Supported | Sem suporte |
| Processamento de documentos | Melhor | Menos estruturado |
Evite SELECT *
Não recupere documentos XML completos quando você só precisa de valores específicos. Use métodos XML para extrair dados do servidor. Essa abordagem reduz o tráfego de rede e evita a análise de grandes documentos XML em Python.
# Create sample XML table for performance demos
cursor.execute("""
CREATE TABLE #XMLPerf (
OrderID INT,
OrderXML XML
)
""")
cursor.execute("""
INSERT INTO #XMLPerf (OrderID, OrderXML) VALUES
(1, '<Order><Customer Name="Alice"/><Item ProductID="1" Qty="2" Price="29.99"/></Order>'),
(2, '<Order><Customer Name="Bob"/><Item ProductID="3" Qty="1" Price="49.99"/></Order>')
""")
# Anti-pattern: Downloads entire XML per row
cursor.execute("SELECT * FROM #XMLPerf")
# Better: Extract only the values you need on the server
cursor.execute("""
SELECT OrderID,
OrderXML.value('(/Order/Customer/@Name)[1]', 'NVARCHAR(100)') AS Customer
FROM #XMLPerf
""")
Tratar XML nulo
Ao consultar dados XML, use COALESCE() para fornecer valores padrão quando os métodos XML retornam NULL.
cursor.execute("""
SELECT OrderID,
COALESCE(OrderXML.value('(/Order/@Total)[1]', 'DECIMAL(10,2)'), 0) AS Total
FROM #XMLPerf
""")