Openquery sql: OPENQUERY (Transact-SQL) — SQL Server

НОУ ИНТУИТ | Лекция | Работа с данными из удаленных источников

< Лекция 9 || Лекция 4: 12345

Аннотация: Прочитав эту лекцию, вы сможете: устанавливать нерегламентированные соединения с различными источниками данных при помощи T-SQL, настроить связанный сервер при помощи T-SQL, настроить связанный сервер через интерфейс Microsoft SQL Server Management Studio, обновить данные на удаленном источнике данных

Ключевые слова: SQL, server, запрос, запись, excel, exchange, чтение данных, источник данных, базы данных, ADO, net, Connection, объект, API, представление, surface area, configuration tools, database engineering, Server Explorer, гранулярность, запрос удаления, удаление хранимой процедуры, management, интерфейс

В лекциях 6-7 курса «Разработка и защита баз данных в Microsoft SQL Server 2005» вы научились переносить локальные данные на удаленные серверы баз данных, использовать разные варианты репликации, которые предлагает SQL Server 2005 и применять службы интеграции SQL Server для взаимодействия с различными источниками данных.

В реальных приложениях приходится работать с данными из различных удаленных источников; не всегда можно или желательно настроить схему репликации — иногда вам просто нужно выполнить единственный запрос, чтобы извлечь информацию в режиме реального времени, не ожидая реплицированных данных.

В этой лекции мы сконцентрируемся на том, как читать данные с удаленных источников и как осуществлять запись на удаленные источники данных в режиме реального времени. Этими источниками данных могут быть либо другие экземпляры SQL Server, либо иные источники данных, например, файлы Microsoft Office Excel или Microsoft Exchange Server.

Если нужно выполнить чтение данных на удаленном источнике данных, необходим способ объявить источник данных назначения, с которым вы хотите связаться и с которого нужно получить данные.

В приложении, которое соединяется с одним сервером базы данных, это обычно реализуется при помощи класса ADO. NET Connection. В этой лекции рассказывается, главным образом, об установлении соединения с удаленным источником данных из SQL Server при помощи кода T-SQL при недоступности ADO.NET.

Чтение данных с удаленных источников в среднем ярусе

Давайте ненадолго вернемся к применению ADO.NET. Чтобы читать данные на удаленных источниках из компонента среднего яруса, вам необходимо открыть объект Connection для каждого из различных источников данных, с которыми вы хотите связаться, и независимо запросить у каждого из них данные, которые нужно извлечь.

Как показано на рис. 4.1, при таком подходе коду среднего яруса приходится выполнять запросы к каждому из этих различных источников данных, используя API доступа каждого источника и выполняя слияние собранных результатов в общий результирующий набор.

Рис.
4.1.
Модель архитектуры для чтения данных с удаленного источника в среднем ярусе

Чтение данных с удаленных источников в среднем ярусе с использованием ADO.

NET

Приложение среднего яруса должно установить соединение с каждым из различных источников данных при помощи соответствующего поставщика доступа к данным. Например:

  • Чтобы подключиться к базе данных Oracle при помощи ADO.NET:
    "Connect to pacific sales
    Dim oracleConn As OracleConnection = New OracleConnection()
        oracleConn.ConnectionString = "Data Source=MyOracleDB;Integrated Security=yes" 
    Dim oracleDA As New OracleDataAdapter("SELECT * FROM PacificSales", oracleConn)
  • Чтобы подключиться к файлу Excel при помощи ADO.NET:
    "Connect to central sales
    Dim excelConn As New OleDbConnection()
        excelConn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" &_
        "Data Source=C:\CentralSales.xls;Extended Properties=""Excel 8.0""" 
    Dim excelDA As New OleDbDataAdapter("SELECT * FROM [Sales$]", excelConn)
  • intuit.ru/2010/edi»>Чтобы подключиться к базе данных SQL Server при помощи ADO.NET:
    "Connect to atlantic sales
    Dim sqlConn As New SqlConnection()
        sqlConn.ConnectionString =
        "Data Source=MySQLServer; Initial Catalog=MySQLDB; Integrated Security=SSPI" 
    Dim sqlDA As New SqlDataAdapter("SELECT * FROM AtlanticSales", sqlConn)

    Затем приложение среднего яруса должно использовать объект DataSet для хранения всех данных, поступивших от различных источников, как в следующем примере кода: (Код этого раздела можно найти среди файлов примеров под именем MiddleTier.vb.txt ).

    Dim salesData as New DataSet() 
    oracleDA.Fill(salesData) 
    excelDA.Fill(salesData) 
    sqlDA.Fill(salesData)

    Обобщаем: при реализации удаленного доступа в среднем ярусе каждый раз, когда необходимы данные о продажах, приложению нужно выполнить следующие действия:

  • Открыть отдельное соединение для каждого удаленного источника данных.
  • intuit.ru/2010/edi»>Перенести данные в средний ярус и слить все результаты в общий результат.

    Среднему ярусу приходится иметь дело с фактом распределения данных по различным физическим местам хранения.

    Иногда слияние данных в среднем ярусе оказывается не такой простой операцией, как в этом примере, поскольку данные могут быть по разному представлены и отформатированы. Код, необходимый для манипуляций с разнородными источниками данных, в программировании в инфраструктуре .NET не всегда одинаков. Например, если нужно извлечь данные из текстового файла, вероятно, вы воспользовались бы классом в пространстве имен System.IO, но если данные нужно было бы извлечь из Active Directory, то, скорее, потребовался бы класс в пространстве имен System.DirectoryServices. Модели программирования для классов в этих пространствах имен весьма различны.

Чтение данных из удаленных источников в SQL Server

Еще один возможный подход в среднем ярусе — это запрос представлений, созданных в SQL Server. Представление должно отвечать за коммуникации со всеми разными источниками данных, выполняя слияние результатов и предоставляя вызывающему приложению один результирующий набор.

Как показано на рис. 4.2, если мы перенесем ответственность за слияние результатов на SQL Server, то сможем воспользоваться преимуществами следующих аспектов:

  • Не нужно объединять средний ярус с физической реализацией.
  • SQL Server может выдать один результирующий набор, независимо от физического распределения данных, поэтому коду среднего яруса гораздо проще осуществлять запись, при этом риск в отношении безопасности, обслуживания, параллельного управления и коммуникаций будет меньше.
  • Обрабатывая промежуточные результирующие наборы от каждого из различных источников данных в SQL Server, мы можем воспользоваться реляционным поисковым механизмом и конструкциями T-SQL для того, чтобы создать более простое, легкое и управляемое решение (см. рис. вверху следующей страницы).

    SQL Server 2005 предлагает два разных подхода к управлению соединениями с удаленными источниками данных:

  • Установление нерегламентируемых соединений с внешними источниками данных, или
  • Статичное управление информацией о конфигурации соединения посредством установки связанного сервера.

    Оба подхода требуют, чтобы удаленный источник данных поддерживал поставщики доступа к данным OLE DB. Это означает, что вы могли бы установить соединение с другими базами данных SQL Server, файловой системы Windows, Microsoft Exchange Server, Windows Active Directory Service, Microsoft Excel или любых других источников данных с поставщиком OLE DB.

    Рис.
    4.2.
    Архитектурная модель для чтения данных из удаленных источников в SQL Server

Читаем данные из удаленного источника данных с использованием нерегламентированных запросов

intuit.ru/2010/edi»>Нерегламентируемые запросы обеспечивают возможность установить соединение с удаленным источником данных и выполнить к нему запрос из кода T-SQL. Это разовое соединение функционирует только в течение выполняемой в данный момент операции.

Включение поддержки нерегламентированных запросов

В SQL Server 2005 поддержка нерегламентированных запросов по умолчанию отключена в интересах безопасности. Выполните перечисленные ниже действия, чтобы применить хранимую процедуру sp_configure для настройки поддержки нерегламентированных запросов или следующую процедуру для выполнения той же задачи через средство SQL Server Surface Area Configuration (Настройка конфигурации контактной зоны SQL Server).

Включаем поддержку нерегламентированных запросов с помощью T-SQL
  1. В меню Start (Пуск) выберите All Programs,. Microsoft SQL Server 2005, SQL Server Management Studio (Все программы, Microsoft SQL Server 2005, Среда SQL Server Management Studio). Откройте окно нового запроса и введите следующий код (который можно найти среди файлов примеров под именем EnableAdHoc.sql в папке SqlScripts.
    sp_configure "show advanced options", 1; 
    GO
    RECONFIGURE; 
    GO
    sp_configure "Ad Hoc Distributed Queries", 1; 
    GO
    RECONFIGURE; 
    GO
  2. Нажмите кнопку Execute (Выполнить).
Включаем поддержку нерегламентированных запросов при помощи средства Настройка конфигурации контактной зоны SQL Server
  1. В меню Start (Пуск) выберите All Programs,. Microsoft SQL Server 2005, Configuration Tools, SQL Server Surface Area Configuration. (Все программы, Microsoft SQL Server 2005, Средства настройки, Настройка контактной зоны SQL Server).
  2. В нижней части главного окна, показанного на следующем рисунке, щелкните ссылку Surface Area Configuration For Features (Настройка контактной зоны для функциональных возможностей).
  3. В окне Surface Area Configuration For Feature (Настройка контактной зоны для функциональных возможностей) перейдите на расположенную слева вкладку View By Instance (Просмотр по экземплярам).
  4. Выделите экземпляр SQL Server, который нужно сконфигурировать, и разверните дерево Database Engine.
  5. Выберите пункт Ad Hoc Remote Queries (Нерегламентированные удаленные запросы) в левой части окна.
  6. Установите флажок Enable OPENROWSET And OPENDATASOURCE Support (Включить поддержку функций OPENROWSET и OPENDATASOURCE ).

Дальше >>

< Лекция 9 || Лекция 4: 12345

Запрос удаленных источников данных в SQL Server

Распространенным действием при написании запросов T-SQL является подключение к локальным базам данных и прямая обработка данных. Но будут ситуации, в которых вам нужно подключиться к удаленной базе данных, расположенной в другом экземпляре на том же сервере или на другом физическом сервере, и обрабатывать ее данные параллельно с локальной обработкой данных.

SQL Server предоставляет нам четыре полезных метода для подключения к удаленным серверам баз данных, даже к другим типам серверов баз данных, и запроса их данных в вашем операторе T-SQL. В этой статье мы обсудим эти четыре метода и способы их использования для запросов к удаленным базам данных SQL Server.

ОТКРЫТЫЙ ИСТОЧНИК ДАННЫХ

Первый метод запроса к удаленной базе данных SQL Server — это функция OPENDATASOURCE T-SQL ниже:

OPENDATASOURCE ( provider_name как char, init_string )

Где provider_name — это поставщик OLE DB, используемый для доступа к источнику данных. А init_string — это строка подключения удаленного сервера.

Чтобы иметь возможность использовать оператор OPENDATASOURCE, вы должны убедиться, что Для раздела реестра DisallowAdhocAccess установлено значение 0 для поставщика, к которому вы хотите подключиться, кроме SQL Server, который можно найти по следующему пути к разделам реестра:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Providers\

Также вам необходимо включить параметр расширенной конфигурации Ad Hoc Distributed Queries , который по умолчанию отключен в SQL Server. Если вы попытаетесь выполнить приведенный ниже простой запрос, использующий оператор T-SQL OPENDATASOURCE, вы получите сообщение об ошибке:

SELECT *  

FROM OPENDATASOURCE(‘SQLNCLI’,  

    ‘Data Source=DEV_SQL;Integrated Security=SSPI’)  

    .testdb.dbo.AddressBook

90 033

Сообщение 15281, уровень 16, состояние 1, строка 1
SQL Server заблокировал доступ к STATEMENT «OpenRowset/OpenDatasource» компонента «Ad Hoc Distributed Queries», поскольку этот компонент отключен как часть конфигурации безопасности для этого сервера. Системный администратор может включить использование «нерегламентированных распределенных запросов» с помощью процедуры sp_configure. Для получения дополнительной информации о включении «Ad Hoc Distributed Queries» выполните поиск «Ad Hoc Distributed Queries» в электронной документации по SQL Server.

Как видно из сообщения об ошибке, параметр расширенной конфигурации Ad Hoc Distributed Queries должен быть включен, чтобы открывать соединение с удаленным сервером с помощью файла OPENDATASOURCE. Этого можно добиться с помощью приведенного ниже запроса sp_configure:

1

2

3

4

5

6

EXEC sp_configure ‘показать дополнительные параметры’, 1

ПЕРЕКОНФИГУРАЦИЯ

GO

EXEC sp_configure ‘специальные распределенные запросы’, 1

RECONFIGURE

GO

После включения параметра расширенной конфигурации Ad Hoc Distributed Queries предыдущий запрос будет выполнен успешно. OPENDATASOURCE может заменить имя сервера в четырехкомпонентном имени таблицы или представления в инструкции SELECT, INSERT, UPDATE или DELETE. Его также можно использовать в операторе EXECUTE для запуска удаленной хранимой процедуры.

ОТКРЫТЫЙ НАБОР

Второй способ запроса базы данных, размещенной на удаленном сервере SQL, — это функция OPENROWSET T-SQL. Чтобы использовать специальный метод OPENROWSET, вам необходимо предоставить всю информацию о подключении, которая требуется для подключения к удаленному серверу SQL и многим другим ресурсам. Его также можно использовать для массовой операции через встроенный поставщик BULK для чтения данных из файлов. OPENROWSET используется в предложении FROM как имя таблицы в операторах SELECT, INSERT, UPDATE или DELETE. Хотя запрос может возвращать несколько наборов результатов, OPENROWSET возвращает только первый.

Для использования OPENROWSET необходимо включить параметр расширенной конфигурации Ad Hoc Distributed Queries , аналогичный функции OPENDATASOURCE.

Вам необходимо указать имя провайдера, строку подключения и запрос следующим образом:

OPENROWSET(‘имя поставщика’, ‘источник данных’,’запрос’)

Вы можете написать предыдущий запрос OPENDATASOURCE с помощью функции OPENROWSET следующим образом:

SELECT a.*  

FROM OPENROWSET(‘SQLNCLI’, ‘Server=DEV_SQL;Trusted_Connection=yes;’,  

       ‘SELECT * FROM testdb. dbo.Profile’) AS a;

Связанный сервер

Связанный сервер SQL Server используется для доступа к удаленным источникам данных OLE DB, таким как экземпляр SQL Server, расположенный за пределами SQL Server или других систем, таких как Oracle, Microsoft Access и Excel, и для выполнения к ним распределенных запросов T-SQL.

Связанный сервер SQL Server отличается от специальных запросов тем, что специальные запросы открывают временное соединение с удаленным сервером и закрывают его, при этом постоянный связанный сервер всегда доступен для использования. Когда пользователь выполняет распределенный запрос к удаленному источнику данных с помощью связанного сервера, SQL Server Engine анализирует эту команду и отправляет запросы в OLE DB. Этот запрос может быть запросом на выполнение или таблицей, которую нужно открыть на этом удаленном сервере.

Связанный сервер можно настроить с помощью SQL Server Management Studio или инструкции T-SQL sp_addlinkedserver.

Чтобы настроить связанный сервер с помощью SQL Server Management Studio, разверните узел Server Objects в окне Object Explorer . Щелкните правой кнопкой мыши узел Linked Server и выберите New Linked Server .

В Общие окна Новый связанный сервер , выберите имя для вашего связанного сервера, затем выберите тип сервера, к которому вам нужно подключиться с помощью этого связанного сервера. Выберите SQL Server , если вам удастся подключиться к удаленному экземпляру SQL Server, или выберите Other Data Source , чтобы выбрать из доступных типов серверов OLE DB из раскрывающегося списка Provider , кроме SQL Server. Если вы выберете SQL Server в качестве типа сервера, имя связанного сервера должно быть сетевым именем удаленного сервера SQL.

Заполните поле Product Name названием продукта выбранного источника данных OLE DB, например SQL Server, если вы подключаетесь к удаленному SQL Server. Введите имя выбранного источника данных в поле Источник данных , например имя экземпляра SQL Server, если вы подключаетесь к удаленному экземпляру SQL Server. Заполните поле Provider String строкой подключения для конкретного поставщика OLE DB, которая идентифицирует уникальный источник данных. Поле местоположения может быть заполнено местоположением удаленной базы данных, интерпретируемым поставщиком OLE DB. Введите имя каталога, который будет использоваться поставщиком OLE DB, в поле Каталог .

Вы не обязаны использовать все описанные аргументы вместе, так как необходимые аргументы зависят от выбранного провайдера. Например, используя поставщика SQL Server, вы будете использовать только два аргумента.

На На странице Security окна New Linked Server укажите контекст безопасности, который связанный сервер будет использовать для подключения исходного SQL Server к удаленному источнику данных. Как следует из названия, в разделе Сопоставление входов на удаленный сервер части окна Безопасность вы можете указать список пользователей, которые могут использовать связанный сервер для подключения к удаленному серверу, сопоставив этих локальных пользователей с входы на удаленный сервер. Эти пользователи могут использовать аутентификацию SQL Server или аутентификацию Windows.

Для логинов, которые не были определены в списке сопоставления, вы должны выбрать контекст безопасности для их подключений к удаленному серверу с использованием этого связанного сервера. Выбор Не делать предотвратит использование этого связанного сервера любым пользователем, не включенным в предыдущий список. При выборе Без использования контекста безопасности пользователи, не включенные в предыдущий список сопоставления, будут подключаться к удаленному серверу с использованием этого связанного сервера без указания для них контекста безопасности. Если вы выберете Быть выполнено с использованием текущего контекста безопасности входа в систему , тогда соединение с удаленным сервером будет установлено с использованием подключающегося пользователя, что является лучшим выбором. В параметре Сделать с использованием этого контекста безопасности укажите учетные данные проверки подлинности SQL Server, которые будут использоваться для установления подключения к удаленному серверу для пользователей, не указанных в списке сопоставления.

Существует множество опций, которые вы можете настроить в зависимости от ваших требований из Параметры сервера окна Новый связанный сервер . Например, установите для параметра Collation Compatible значение true, если вы уверены, что удаленный источник данных имеет тот же набор символов и порядок сортировки, что и локальный сервер. По умолчанию SQL Server локально оценивает сравнение символьных столбцов, если вы не используете этот параметр. Параметр Data Access используется для включения и отключения доступа к распределенным запросам для связанного сервера. Чтобы включить удаленный вызов процедуры из указанный сервер установил для RPC значение true, а для включения удаленного вызова процедуры с по указанный сервер установил для RPC Out значение true.

Решение о том, будет ли в запросе использоваться сопоставление локального или удаленного сервера, определяется параметром Use Remote Collation . Если значение этого параметра равно true, вы можете указать имя сопоставления, которое будет использоваться удаленным сервером, в параметре Имя сопоставления . Это применимо, если удаленный источник данных не является SQL Server, где в этом поле можно указать любое имя сопоставления, поддерживаемое SQL Server.

Вы можете переопределить время ожидания удаленного входа в систему сервера по умолчанию для этого связанного сервера, изменив параметр Время ожидания соединения на любое значение больше 0. Это значение указывает время ожидания в секундах для подключения к связанному серверу. Также вы можете указать время ожидания в секундах для запросов на подключение к связанному серверу, изменив параметр Query Timeout на любое значение больше 0. Это переопределит время ожидания удаленного запроса сервера 9.0014 для связанного сервера.

Еще одна полезная опция, которая используется для запуска распределенной транзакции при вызове удаленной хранимой процедуры, в которой эта транзакция будет управляться и защищаться MS DTC. Этот параметр называется Включить продвижение распределенных транзакций.

Вы можете убедиться, что связанный сервер работает нормально, щелкнув правой кнопкой мыши на этом связанном сервере и выбрав Test Connection 9.0020 следующим образом:

Если соединение с удаленным сервером открыто успешно, вы получите следующее сообщение, в противном случае будет отображаться сообщение об ошибке, показывающее, что есть что-то, препятствующее открытию соединения:

Вы можете легко создать предыдущий связанный сервер, используя оператор sp_addlinkedserver T-SQL, передав необходимые аргументы следующим образом:

USE [мастер]

GO

EXEC master. dbo.sp_addlinkedserver @server = N’DEV_SQL’, @srvproduct=N’SQL Server’

GO

После успешного создания связанного сервера вы сможете использовать его, указав имя из четырех частей, которое включает: Linked_Server_Name.Remote_Database_Name.Schema_Name.Table_Name , как в приведенном ниже примере:

ВЫБЕРИТЕ * ИЗ DEV_SQL.testdb.dbo.Profile

GO

ОТКРЫТЫЙ ЗАПРОС

Последний метод SQL Server, который используется для подключения к удаленному источнику данных, — это функция OPENQUERY . Это альтернативный одноразовый специальный метод подключения к удаленному серверу с использованием связанного сервера. Для более частых подключений к удаленному серверу лучше использовать связанный сервер вместо функции OPENQUERY.

Функцию OPENQUERY можно использовать в предложении FROM оператора SELECT, INSERT, UPDATE или DELETE, заменяя имя таблицы. Он принимает два аргумента; имя связанного сервера и запрос. Эти параметры не могут быть переменными, а именно:

OPENQUERY (связанный_сервер, ‘запрос’)

Ниже приведен простой пример использования OPENQUERY:

SELECT * FROM OPENQUERY(DEV_SQL,’SELECT * FROM testdb.dbo.Profile’)

Сравнение

При использовании связанного сервера для запроса удаленного сервера оптимизатор запросов создаст план выполнения после классификации и разделения запроса на локальные и удаленные запросы, где локальные запросы будут выполняться локально, а удаленные запросы будут отправляться на удаленный сервер, а затем объединяются для отображения конечного результата пользователю в виде единого набора результатов. Другим недостатком связанного сервера является то, что на удаленном сервере не будет применяться фильтрация, если в запросе есть предложение WHERE, где он будет извлекать все записи из удаленной таблицы и выполнять фильтрацию и объединение локально.

В случае функции OpenQuery SQL Engine не будет пытаться классифицировать запрос или проверять, что он будет делать, он просто отправит запрос как есть на удаленный сервер. Разбор SQL-запроса, генерация плана выполнения и вся фильтрация будут выполняться на удаленном сервере.

В общем, OpenQuery быстрее, чем связанный сервер, так как SQL Engine не прерывает запрос перед его отправкой на удаленный сервер, но полезен только для однократных менее частых удаленных подключений.

Используя функции OPENROWSET и OPENDATASOURCE , вы должны каждый раз указывать все детали подключения, включая имя пользователя и пароль. Хотя эти функции не обеспечивают всех функций связанного сервера, таких как управление безопасностью, они потребляют меньше ресурсов вашего сервера. Поскольку эти функции открывают одноразовое соединение с удаленным сервером, лучше использовать связанный сервер для частого доступа к удаленному серверу.

  • Автор
  • Последние сообщения

Ахмад Ясин

Ахмад Ясин — инженер Microsoft по работе с большими данными, обладающий глубокими знаниями и опытом в области SQL BI, администрирования и разработки баз данных SQL Server.

Он является сертифицированным экспертом Microsoft по решениям в области управления данными и аналитики, сертифицированным специалистом по решениям Microsoft в области администрирования и разработки баз данных SQL, специалистом по разработке Azure и сертифицированным тренером Microsoft.

Кроме того, он публикует свои советы по SQL во многих блогах.

Просмотреть все сообщения Ахмада Ясина

Последние сообщения Ахмада Ясина (посмотреть все)

sql — Как присоединить OpenQuery к другому оператору Select?

Задавать вопрос

спросил

Изменено
1 год, 2 месяца назад

Просмотрено
312 раз

Я написал заявление, используя OpenQuery , и теперь хочу присоединить его к другому моему запросу, чтобы при запуске представления оно возвращало таблицу с записями из обоих вариантов. Как бы я это сделал?

Вот запросы, которые у меня сейчас есть:

 SELECT I.Invoice_ID,
        I.Invoice_Num,
        I.SO_ID,
        I.SO_Num,
        O. Номер счета,
        I.ShipZip как почтовый индекс,
        I.RequestedDeliveryDate AS Дата доставки,
        I.ДобавитьДату,
        I.Добавить пользователя,
        O.OrgName,
        I.[Статус]
    ОТ dbo.Org O
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ dbo.Invoice I ON O.Org_ID = I.Org_ID
(SELECT * FROM OPENQUERY ([TEST-SQL-TEST-02], 'SELECT GoodsOutTest, LoadRef FROM TestWMS.dbo.GoodsTest')
 
  • sql
  • sql-сервер
  • открытый запрос

1

Почему бы не просто буквально ПРИСОЕДИНИТЬСЯ к нему ?

 ВЫБЕРИТЕ I.Invoice_ID,
I.Invoice_Num,
I.SO_ID,
I.SO_Num,
O. Номер счета,
I.ShipZip как почтовый индекс,
I.RequestedDeliveryDate AS Дата доставки,
I.ДобавитьДату,
I.Добавить пользователя,
O.