Извлечение результирующих наборов в потоки

Вместо получения результатов в традиционном объекте Recordset ADO может получить результаты запроса в потоке. Для хранения этих результатов можно использовать объект ADO Stream (или другие объекты, поддерживающие интерфейс COM IStream , например объекты ASP Request и Response ). Одним из способов использования этой функции является получение результатов в формате XML. Например, при использовании SQL Server результаты XML можно возвращать несколькими способами, например с помощью предложения FOR XML с SQL-запросом SELECT или запроса XPath.

Чтобы получить результаты запроса в потоковом формате, а не в Recordset, необходимо указать константу adExecuteStream из ExecuteOptionEnum в качестве параметра метода Execute объекта Command . Если поставщик поддерживает эту функцию, результаты будут возвращены в потоке после выполнения. Перед выполнением кода может потребоваться указать дополнительные свойства, зависящие от поставщика. Например, для поставщика Microsoft OLE DB для SQL Server необходимо указать такие свойства, как Выходной поток в коллекции Properties объекта Command. Дополнительные сведения о SQL Server динамических свойствах, связанных с этой функцией, см. в разделе Свойства XML-Related электронной документации по SQL Server.

Пример запроса FOR XML

Следующий пример записывается на VBScript в базу данных Northwind:

<!-- BeginRecordAndStreamVBS -->  
<%@ LANGUAGE = VBScript %>  
<%  Option Explicit      %>  
  
<HTML>  
<HEAD>  
<META NAME="GENERATOR" Content="Microsoft Developer Studio"/>  
<META HTTP-EQUIV="Content-Type" content="text/html"; charset="iso-8859-1">  
<TITLE>FOR XML Query Example</TITLE>  
  
<STYLE>  
   BODY  
   {  
      FONT-FAMILY: Tahoma;  
      FONT-SIZE: 8pt;  
      OVERFLOW: auto  
   }  
  
   H3  
   {  
      FONT-FAMILY: Tahoma;  
      FONT-SIZE: 8pt;  
      OVERFLOW: auto  
   }  
</STYLE>  
  
<!-- #include file="adovbs.inc" -->  
<%  
   Response.Write "<H3>Server-side processing</H3>"  
  
   Response.Write "Page Generated @ " & Now() & "<BR/>"  
  
   Dim adoConn  
   Set adoConn = Server.CreateObject("ADODB.Connection")  
  
   Dim sConn  
   sConn = "Provider=SQLOLEDB;Data Source=" & _  
      Request.ServerVariables("SERVER_NAME") & ";" & _  
      Initial Catalog=Northwind;Integrated Security=SSPI;"  
  
   Response.write "Connect String = " & sConn & "<BR/>"  
  
   adoConn.ConnectionString = sConn  
   adoConn.CursorLocation = adUseClient  
  
   adoConn.Open  
  
   Response.write "ADO Version = " & adoConn.Version & "<BR/>"  
   Response.write "adoConn.State = " & adoConn.State & "<BR/>"  
  
   Dim adoCmd  
   Set adoCmd = Server.CreateObject("ADODB.Command")  
   Set adoCmd.ActiveConnection = adoConn  
  
   Dim sQuery  
   sQuery = "<ROOT xmlns:sql='urn:schemas-microsoft-com:xml-sql'><sql:query>SELECT * FROM PRODUCTS WHERE ProductName='Gumbr Gummibrchen' FOR XML AUTO</sql:query></ROOT>"  
  
   Response.write "Query String = " & sQuery & "<BR/>"  
  
   Dim adoStreamQuery  
   Set adoStreamQuery = Server.CreateObject("ADODB.Stream")  
   adoStreamQuery.Open  
   adoStreamQuery.WriteText sQuery, adWriteChar  
   adoStreamQuery.Position = 0  
  
   adoCmd.CommandStream = adoStreamQuery  
   adoCmd.Dialect = "{5D531CB2-E6Ed-11D2-B252-00C04F681B71}"  
  
   Response.write "Pushing XML to client for processing "  & "<BR/>"  
  
   adoCmd.Properties("Output Stream") = Response  
   Response.write "<XML ID='MyDataIsle'>"  
   adoCmd.Execute , , 1024  
   Response.write "</XML>"  
  
%>  
  
<SCRIPT language="VBScript" For="window" Event="onload">  
   Dim xmlDoc  
   Set xmlDoc = MyDataIsle.XMLDocument  
   xmlDoc.resolveExternals=false  
   xmlDoc.async=false  
  
   If xmlDoc.parseError.Reason <> "" then  
      Msgbox "parseError.Reason = " & xmlDoc.parseError.Reason  
   End If  
  
   Dim root, child  
   Set root = xmlDoc.documentElement  
   For each child in root.childNodes  
      dim OutputXML  
      OutputXML = document.all("log").innerHTML  
      document.all("log").innerHTML = OutputXML & "<LI>" & child.getAttribute("ProductName") & "</LI>"  
   Next  
</SCRIPT>  
  
</HEAD>  
  
<BODY>  
  
   <H3>Client-side processing of XML Document MyDataIsle</H3>  
   <UL id=log>  
   </UL>  
  
</BODY>  
</HTML>  
<!-- EndRecordAndStreamVBS -->  
  

Предложение FOR XML указывает SQL Server возвращать данные в виде XML-документа.

Синтаксис FOR XML

FOR XML [RAW|AUTO|EXPLICIT]  

FOR XML RAW создает универсальные элементы строк, которые имеют значения столбцов в качестве атрибутов. FOR XML AUTO использует эвристические методы для создания иерархического дерева с именами элементов на основе имен таблиц. FOR XML EXPLICIT создает универсальную таблицу со связями, полностью описанными в метаданных.

Ниже приведен пример инструкции SQL SELECT FOR XML:

SELECT * FROM PRODUCTS ORDER BY PRODUCTNAME FOR XML AUTO  

Команду можно указать в строке, как показано ранее, назначить CommandText или в виде запроса шаблона XML, назначенного CommandStream. Дополнительные сведения о запросах шаблонов XML см. в разделах Потоки команд в ADO или Использование потоков для ввода команд в электронной документации по SQL Server.

В качестве запроса шаблона XML запрос FOR XML выглядит следующим образом:

<sql:query> SELECT * FROM PRODUCTS ORDER BY PRODUCTNAME FOR XML AUTO </sql:query>  

В этом примере указывается объект ОТВЕТА ASP для свойства Output Stream :

adoCmd.Properties("Output Stream") = Response  

Затем укажите параметр adExecuteStreamдля параметра Execute. В этом примере поток упаковывается в xml-теги для создания острова XML-данных:

Response.write "<XML ID=MyDataIsle>"  
adoCmd.Execute , , adExecuteStream  
Response.write "</XML>"  

Комментарии

На этом этапе XML-код передается в клиентский браузер и готов к отображению. Для этого используется клиентский VBScript для привязки XML-документа к экземпляру модели DOM и циклического перебора каждого дочернего узла для создания списка продуктов в HTML.