Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Коннектор к веб-службам. MS SQL 2000  [new]
YoriKim
Member

Откуда:
Сообщений: 35
На одном хосте нужно вызвать веб-службу из хранимой процедуры. Как это можно сделать в MS SQL 2000?
15 июл 08, 08:56    [5933636]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Knyazev Alexey
Member

Откуда: Екб -> Мск
Сообщений: 10234
Блог
sp_OA...
ESP

???
15 июл 08, 09:40    [5933831]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
YoriKim
Member

Откуда:
Сообщений: 35
saop
15 июл 08, 09:42    [5933848]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
YoriKim
Member

Откуда:
Сообщений: 35
soap*
15 июл 08, 09:44    [5933863]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
YoriKim
На одном хосте нужно вызвать веб-службу из хранимой процедуры. Как это можно сделать в MS SQL 2000?
Вариант - OLE Automation.
Вот код для примера на 2005м.
CREATE PROCEDURE [dbo].[spSOAPMethodCall] (
	 @@URL		SysName
	,@@Header	XML	= NULL	OUTPUT
	,@@Body		XML	= NULL	OUTPUT
) AS BEGIN
	-- Для установки Proxy воспользуйтесь "proxycfg -u"

	DECLARE	 @OLEObject		Int
		,@HTTPStatus		Int
		,@ErrCode		Int
		,@ErrMethod		SysName
		,@ErrSource		SysName
		,@ErrDescription	SysName
		,@@SOAPAction		SysName
		,@Request		XML

	;WITH XMLNAMESPACES (
		 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
		,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
		,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
	SELECT	 @@SOAPAction	= @@Body.value('namespace-uri(/*[1])','SysName') + @@Body.value('local-name(/*[1])','SysName')
		,@Request	= (
	SELECT	 @@Header	AS [soap:Header]
		,@@Body		AS [soap:Body]
	FOR	XML Path('soap:Envelope'),Type)

	EXEC @ErrCode = sys.sp_OACreate 'MSXML2.ServerXMLHTTP', @OLEObject OUT
	IF (@ErrCode = 0) BEGIN
		EXEC @ErrCode = sys.sp_OAMethod @OLEObject ,'open'		,NULL ,'POST' ,@@URL ,'false'				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'open'		GOTO Error END
		EXEC @ErrCode = sys.sp_OAMethod @OLEObject ,'setRequestHeader'	,NULL ,'Content-Type'	,'text/xml; charset=utf-8'	IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO Error END
		EXEC @ErrCode = sys.sp_OAMethod @OLEObject ,'setRequestHeader'	,NULL ,'SOAPAction'	,@@SOAPAction			IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO Error END
		EXEC @ErrCode = sys.sp_OAMethod @OLEObject ,'send'		,NULL ,@Request						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'send'		GOTO Error END

		EXEC @ErrCode = sys.sp_OAGetProperty @OLEObject ,'status' ,@HTTPStatus OUT						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'status'		GOTO Error END
		IF (@HTTPStatus IN (200,500)) BEGIN
			DECLARE	@Response TABLE ( Response NVarChar(max) )
			INSERT	@Response
			EXEC @ErrCode = sys.sp_OAGetProperty @OLEObject ,'responseText'							IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'responseText'	GOTO Error END

			;WITH XMLNAMESPACES (
				 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
				,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
				,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
			SELECT	 @@Header	= R.X.query('/soap:Envelope/soap:Header/*')
				,@@Body		= R.X.query('/soap:Envelope/soap:Body/*')
			FROM	@Response CROSS APPLY (SELECT Convert(XML,Replace(Response,' encoding="utf-8"','')) AS X) R
			-- Fault
			;WITH XMLNAMESPACES (
				 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
				,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
				,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
			SELECT	 @ErrMethod	= @@SOAPAction
				,@ErrSource	= @@Body.value('(/soap:Fault/faultcode)[1]'	,'SysName')
				,@ErrDescription= @@Body.value('(/soap:Fault/faultstring)[1]'	,'SysName')
			WHERE	@HTTPStatus = 500
		END ELSE
			SELECT	 @ErrMethod	= 'send'
				,@ErrSource	= 'spSOAPMethod'
				,@ErrDescription= 'Ошибоный статус HTTP ответа "' + Convert(VarChar,@HTTPStatus) + '"'

		GOTO Destroy
	Error:	EXEC @ErrCode = sys.sp_OAGetErrorInfo @OLEObject ,@ErrSource OUT ,@ErrDescription OUT
	Destroy:EXEC @ErrCode = sys.sp_OADestroy @OLEObject
		IF (@ErrSource IS NOT NULL) BEGIN
			RAISERROR('Ошибка при выполнении метода "%s" в "%s": %s',18,1,@ErrMethod,@ErrSource,@ErrDescription)
			IF (@@TranCount > 0 AND XACT_STATE() != 0)
				ROLLBACK
			RETURN	@@Error
		END
	END ELSE BEGIN
		RAISERROR('Ошибка при создании OLE объекта "MSXML2.ServerXMLHTTP"',18,1)
		RETURN	@@Error
	END
END
GO
Вызов делается так:
DECLARE	 @URL		SysName
	,@Header	XML
	,@Body		XML
-- Создание запроса
;WITH XMLNAMESPACES (DEFAULT '<WebService URI>')
SELECT	 @URL	= '<WebService URL>'
	,@Body		= (
SELECT	 <WebMethod Param1 Value>	AS [WebMethod Param1 Name]
	,<WebMethod ParamN Value>	AS [WebMethod ParamN Name]
FOR	XML Path('<WebMethod Name>'),Type)
-- Вызов WebMethod-а
EXEC	dbo.spSOAPMethodCall
		 @URL
		,@Header	OUT	
		,@Body		OUT
-- Результат
SELECT	 @Header
	,@Body
15 июл 08, 09:54    [5933931]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
YoriKim
Member

Откуда:
Сообщений: 35
Спасибо. Сейчас буду портировать на 2000 :)
15 июл 08, 10:12    [5934058]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Есть одна неприятная весчть в OLE Automation: Это чтение значений более 8000 символов.
В выше приведённом случае это решается через INSERT EXEC. Но у него свои ограничеия использования (например, внутре другого INSERT EXEC).
Вот жалкие попытки обойти:
ALTER PROCEDURE [dbo].[spSOAPMethodCall] (
	 @@URL		SysName
	,@@Header	XML	= NULL	OUTPUT
	,@@Body		XML	= NULL	OUTPUT
	,@@TimeOut	Int	= 900000
) WITH EXECUTE AS 'dbo' AS BEGIN
	-- Для установки Proxy воспользуйтесь "proxycfg -u"
	DECLARE	 @OLEHTTP		Int
		,@OLEStream		Int
		,@HTTPStatus		Int
		,@ErrCode		Int
		,@ErrMethod		SysName
		,@ErrSource		SysName
		,@ErrDescription	SysName
		,@@SOAPAction		SysName
		,@Request		XML
		,@Response		NVarChar(max)
		,@EOF			Bit

	-- OLE HTTPRequest
	EXEC @ErrCode = sys.sp_OACreate 'MSXML2.ServerXMLHTTP' ,@OLEHTTP OUT
	IF (@ErrCode != 0)
		SELECT	 @ErrMethod	= 'MSXML2.ServerXMLHTTP'
			,@ErrSource	= 'sp_OACreate'
			,@ErrDescription= 'Ошибка создания OLE объекта'
	ELSE BEGIN
		-- Генерация SOAP запроса
		;WITH XMLNAMESPACES (
			 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
			,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
			,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
		SELECT	 @@SOAPAction	= @@Body.value('namespace-uri(/*[1])','SysName') + @@Body.value('local-name(/*[1])','SysName')
			,@Request	= (
		SELECT	 @@Header	AS [soap:Header]
			,@@Body		AS [soap:Body]
		FOR	XML Path('soap:Envelope'),Type)
		-- Установка TimeOut, HTTTP параметров, запрос
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'setTimeouts'	,NULL ,5000 ,60000 , 30000, @@TimeOut				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setTimeouts'		GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'open'		,NULL ,'POST' ,@@URL ,'false'				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'open'		GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'setRequestHeader'	,NULL ,'Content-Type'	,'text/xml; charset=utf-8'	IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'setRequestHeader'	,NULL ,'SOAPAction'	,@@SOAPAction			IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'send'		,NULL ,@Request						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'send'		GOTO HTTPError END
		-- Проверка сатуса HTTP ответа
		EXEC @ErrCode = sys.sp_OAGetProperty @OLEHTTP ,'status' ,@HTTPStatus OUT						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'status'		GOTO HTTPError END
		IF (@HTTPStatus IN (200,500)) BEGIN
			-- Временый файл для постепенной закачки
			-- необходим вместо метода INSERT EXEC (> 8000 сииволов)
			-- Для отсутствия перекрытия параллельных запросов имя файл привязывается к OLE объекту по номеру
			SELECT	 @@SOAPAction	= Convert(VarChar,@OLEHTTP) + '.xml'
				,@Response	= ''
			EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'responseXml.save' ,NULL ,@@SOAPAction				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'responceXml'		GOTO HTTPError END
			-- Закачка файла в переменную через OLE Stream
			EXEC @ErrCode = sys.sp_OACreate 'ADODB.Stream' ,@OLEStream OUT
			IF (@ErrCode != 0)
				SELECT	 @ErrMethod	= 'ADODB.Stream'
					,@ErrSource	= 'sp_OACreate'
					,@ErrDescription= 'Ошибка создания OLE объекта'
			ELSE BEGIN
				-- Открытие, установка парметров, указание файла
				EXEC @ErrCode = sys.sp_OAMethod @OLEStream ,'Open'							IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'Open'		GOTO StreamError END
				EXEC @ErrCode = sys.sp_OASetProperty @OLEStream ,'CharSet' ,'utf-8'					IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'CharSet'		GOTO StreamError END
				EXEC @ErrCode = sys.sp_OAMethod @OLEStream ,'LoadFromFile' ,NULL, @@SOAPAction				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'LoadFromFile'	GOTO StreamError END
				-- Для обхода "особенности" чтения utf-8
				EXEC @ErrCode = sys.sp_OAMethod @OLEStream ,'ReadText' ,@ErrDescription OUT, 2				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'ReadText'		GOTO StreamError END
				-- Рекурсивное порциальное чтение
				WHILE (1 = 1) BEGIN
					-- Проверка достижения конца файла
					EXEC @ErrCode = sys.sp_OAGetProperty @OLEStream ,'EOS' ,@EOF OUT				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'EOS'			GOTO StreamError END
					IF (@EOF = 1) BREAK
					-- Чтение очережной порции
					EXEC @ErrCode = sys.sp_OAMethod @OLEStream ,'ReadText' ,@ErrDescription OUT, 128		IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'ReadText'		GOTO StreamError END
					SET @Response = @Response + @ErrDescription
				END
				-- Закрытие Stream
				EXEC @ErrCode = sys.sp_OAMethod @OLEStream ,'Close'							IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'Close'		GOTO StreamError END
				-- Уничтожение Stream
				GOTO StreamDestroy
				StreamError:	EXEC @ErrCode = sys.sp_OAGetErrorInfo @OLEStream ,@ErrSource OUT ,@ErrDescription OUT
				StreamDestroy:	EXEC @ErrCode = sys.sp_OADestroy @OLEStream
				-- Парсирование SOAP ответа
				IF (@ErrSource IS NULL) BEGIN
					;WITH XMLNAMESPACES (
						 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
						,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
						,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
					SELECT	 @@Header	= R.X.query('/soap:Envelope/soap:Header/*')
						,@@Body		= R.X.query('/soap:Envelope/soap:Body/*')
					FROM	(SELECT Convert(XML,Replace(@Response,' encoding="utf-8"','')) AS X) R
					-- Парсирование SOAP ошибки
					;WITH XMLNAMESPACES (
						 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
						,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
						,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
					SELECT	 @ErrMethod	= @@SOAPAction
						,@ErrSource	= @@Body.value('(/soap:Fault/faultcode)[1]'	,'SysName')
						,@ErrDescription= @@Body.value('(/soap:Fault/faultstring)[1]'	,'SysName')
					WHERE	@HTTPStatus = 500
				END
			END
		END ELSE
			SELECT	 @ErrMethod	= 'send'
				,@ErrSource	= 'spSOAPMethod'
				,@ErrDescription= 'Ошибочный статус HTTP ответа "' + Convert(VarChar,@HTTPStatus) + '"'
		-- Уничтожение HTTPRequest
		GOTO HTTPDestroy
		HTTPError:	EXEC @ErrCode = sys.sp_OAGetErrorInfo @OLEHTTP ,@ErrSource OUT ,@ErrDescription OUT
		HTTPDestroy:	EXEC @ErrCode = sys.sp_OADestroy @OLEHTTP
	END
	-- Вывод ошибок
	IF (@ErrSource IS NOT NULL) BEGIN
		RAISERROR('Ошибка при выполнении метода "%s" в "%s": %s',18,1,@ErrMethod,@ErrSource,@ErrDescription)
		RETURN	@@Error
	END
END
GO
Жалкие, потому-что нужен доступ к файловой системе. :(
25 июл 08, 20:02    [5988363]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Подправим вариант для INSERT EXEC. Особенно актуально для вызова из Job-а, т.к. размер строковых данных не устанавливается максимальным, как это делается для нативного клиента.
Mnior
CREATE PROCEDURE [dbo].[spSOAPMethodCall] (
	 @@URL		SysName
	,@@Header	XML	= NULL	OUTPUT
	,@@Body		XML	= NULL	OUTPUT
) AS BEGIN
	-- Для установки Proxy воспользуйтесь "proxycfg -u"

	DECLARE	 @OLEObject		Int
		,@HTTPStatus		Int
		,@ErrCode		Int
		,@ErrMethod		SysName
		,@ErrSource		SysName
		,@ErrDescription	SysName
		,@@SOAPAction		SysName
		,@Request		XML

	;WITH XMLNAMESPACES (
		 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
		,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
		,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
	SELECT	 @@SOAPAction	= @@Body.value('namespace-uri(/*[1])','SysName') + @@Body.value('local-name(/*[1])','SysName')
		,@Request	= (
	SELECT	 @@Header	AS [soap:Header]
		,@@Body		AS [soap:Body]
	FOR	XML Path('soap:Envelope'),Type)

	EXEC @ErrCode = sys.sp_OACreate 'MSXML2.ServerXMLHTTP', @OLEObject OUT
	IF (@ErrCode = 0) BEGIN
		EXEC @ErrCode = sys.sp_OAMethod @OLEObject ,'open'		,NULL ,'POST' ,@@URL ,'false'				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'open'		GOTO Error END
		EXEC @ErrCode = sys.sp_OAMethod @OLEObject ,'setRequestHeader'	,NULL ,'Content-Type'	,'text/xml; charset=utf-8'	IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO Error END
		EXEC @ErrCode = sys.sp_OAMethod @OLEObject ,'setRequestHeader'	,NULL ,'SOAPAction'	,@@SOAPAction			IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO Error END
		EXEC @ErrCode = sys.sp_OAMethod @OLEObject ,'send'		,NULL ,@Request						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'send'		GOTO Error END

		EXEC @ErrCode = sys.sp_OAGetProperty @OLEObject ,'status' ,@HTTPStatus OUT						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'status'		GOTO Error END
		IF (@HTTPStatus IN (200,500)) BEGIN
			DECLARE	@Response TABLE ( Response NVarChar(max) )
			SET TEXTSIZE 2147483647;
			INSERT	@Response
			EXEC @ErrCode = sys.sp_OAGetProperty @OLEObject ,'responseText'							IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'responseText'	GOTO Error END

			;WITH XMLNAMESPACES (
				 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
				,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
				,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
			SELECT	 @@Header	= R.X.query('/soap:Envelope/soap:Header/*')
				,@@Body		= R.X.query('/soap:Envelope/soap:Body/*')
			FROM	@Response CROSS APPLY (SELECT Convert(XML,Replace(Response,' encoding="utf-8"','')) AS X) R
			-- Fault
			;WITH XMLNAMESPACES (
				 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
				,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
				,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
			SELECT	 @ErrMethod	= @@SOAPAction
				,@ErrSource	= @@Body.value('(/soap:Fault/faultcode)[1]'	,'SysName')
				,@ErrDescription= @@Body.value('(/soap:Fault/faultstring)[1]'	,'SysName')
			WHERE	@HTTPStatus = 500
		END ELSE
			SELECT	 @ErrMethod	= 'send'
				,@ErrSource	= 'spSOAPMethod'
				,@ErrDescription= 'Ошибоный статус HTTP ответа "' + Convert(VarChar,@HTTPStatus) + '"'

		GOTO Destroy
	Error:	EXEC @ErrCode = sys.sp_OAGetErrorInfo @OLEObject ,@ErrSource OUT ,@ErrDescription OUT
	Destroy:EXEC @ErrCode = sys.sp_OADestroy @OLEObject
		IF (@ErrSource IS NOT NULL) BEGIN
			RAISERROR('Ошибка при выполнении метода "%s" в "%s": %s',18,1,@ErrMethod,@ErrSource,@ErrDescription)
			IF (@@TranCount > 0 AND XACT_STATE() != 0)
				ROLLBACK
			RETURN	@@Error
		END
	END ELSE BEGIN
		RAISERROR('Ошибка при создании OLE объекта "MSXML2.ServerXMLHTTP"',18,1)
		RETURN	@@Error
	END
END
GO
11 апр 11, 10:26    [10499359]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Лишние переменные, вызовы а главное баг, сильно влияют на производительность.
+ Код
ALTER PROCEDURE [dbo].[spSOAPMethodCall] (
	 @@URL		SysName
	,@@Header	XML	= NULL	OUTPUT
	,@@Body		XML	= NULL	OUTPUT
	,@@TimeOut	Int	= 900000
	,@@OutError	Bit	= 0
) WITH EXECUTE AS 'dbo' AS BEGIN
	-- Для установки Proxy воспользуйтесь "proxycfg -u"
	DECLARE	 @OLEHTTP	Int
		,@HTTPStatus	Int
		,@ErrCode	Int
		,@ErrMethod	SysName
		,@ErrSource	SysName
		,@ErrDescript	NVarChar(4000)
		,@SOAPAction	SysName
		,@Length	Int
		,@Request	XML
		,@Response	XML

	-- OLE HTTPRequest
	EXEC @ErrCode = sys.sp_OACreate 'MSXML2.ServerXMLHTTP' ,@OLEHTTP OUT
	IF (@ErrCode != 0)
		SELECT	 @ErrMethod	= 'MSXML2.ServerXMLHTTP'
			,@ErrSource	= 'sp_OACreate'
			,@ErrDescript	= 'Ошибка создания OLE объекта'
	ELSE BEGIN
		-- Генерация SOAP запроса
		;WITH XMLNAMESPACES (
			 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
			,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
			,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
		SELECT	 @SOAPAction	= CASE	WHEN xmlns LIKE '%/'
						THEN xmlns       + method
						ELSE xmlns + '/' + method
						END
			,@Request	= (
		SELECT	 @@Header	AS [soap:Header]
			,@@Body		AS [soap:Body]
		FOR	XML Path('soap:Envelope'),Type)
		FROM	(SELECT	 @@Body.value('namespace-uri(/*[1])','SysName')
				,@@Body.value('local-name(/*[1])'   ,'SysName')) S(xmlns,method)
		-- Установка TimeOut, HTTTP параметров, запрос
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'setTimeouts'	,NULL ,5000 ,60000 , 30000, @@TimeOut				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setTimeouts'		GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'open'		,NULL ,'POST' ,@@URL ,'false'				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'open'		GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'setRequestHeader'	,NULL ,'Content-Type'	,'text/xml; charset=utf-8'	IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'setRequestHeader'	,NULL ,'SOAPAction'	,@SOAPAction			IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'send'		,NULL ,@Request						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'send'		GOTO HTTPError END
		-- Проверка сатуса HTTP ответа
		EXEC @ErrCode = sys.sp_OAGetProperty @OLEHTTP ,'status' ,@HTTPStatus OUT						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'status'		GOTO HTTPError END
		IF (@HTTPStatus IN (200,500)) BEGIN
			-- Длина ответа, лучше не делать так - нестабильные баги (говно код)
			EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'getResponseHeader' ,@Length OUT ,'Content-Length'			IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'getResponseHeader'	GOTO HTTPError END
			IF (@Length > 4000) BEGIN	-- Не умещается в переменную
				DECLARE	@TResponse TABLE (Response NVarChar(max))
				SET TEXTSIZE 2147483647;-- Используем глючный вариант
				INSERT @TResponse
				EXEC @ErrCode = sys.sp_OAGetProperty @OLEHTTP ,'responseText'						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'responseText'	GOTO HTTPError END
				SELECT @Response = Convert(XML,Stuff(Response    ,1,IsNull(NullIf(CharIndex('?>',Response    ),0)+1,0),'')) FROM @TResponse
			END ELSE BEGIN			-- Умещается в переменную
				EXEC @ErrCode = sys.sp_OAGetProperty @OLEHTTP ,'responseText' ,@ErrDescript OUT				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'responseText'	GOTO HTTPError END
				SELECT @Response = Convert(XML,Stuff(@ErrDescript,1,IsNull(NullIf(CharIndex('?>',@ErrDescript),0)+1,0),''))
			END
			-- Парсирование SOAP ответа
			;WITH XMLNAMESPACES (
				 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
				,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
				,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
			SELECT	 @@Header	= R.Response.query('/soap:Envelope/soap:Header/node()')
				,@@Body		= R.Response.query('/soap:Envelope/soap:Body/node()')
			FROM	(SELECT @Response)R(Response)
				-- Парсирование SOAP ошибки
		IF (@HTTPStatus = 500)
			WITH XMLNAMESPACES (
				 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
				,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
				,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
			SELECT	 @ErrMethod	= @SOAPAction
				,@ErrSource	= Coalesce(
						  B.Body.value('(/soap:Fault/faultactor)[1]'	,'SysName')
						 ,B.Body.value('(/soap:Fault/faultcode)[1]'	,'SysName')
						 ,'soap:Server')
				,@ErrDescript	= IsNull(
						  B.Body.value('(/soap:Fault/faultstring)[1]'	,'NVarChar(4000)')
						+ IsNull(
						  B.Body.value('(/soap:Fault/detail)[1]'	,'NVarChar(4000)')
						 ,''),'Unknown Error')
			FROM	(SELECT @@Body)	  B(Body)
		END ELSE
			SELECT	 @ErrMethod	= 'send'
				,@ErrSource	= 'spSOAPMethod'
				,@ErrDescript	= 'Ошибочный статус HTTP ответа "' + Convert(VarChar,@HTTPStatus) + '"'
		-- Уничтожение HTTPRequest
		GOTO HTTPDestroy
		HTTPError:	EXEC @ErrCode = sys.sp_OAGetErrorInfo @OLEHTTP ,@ErrSource OUT ,@ErrDescript OUT
		HTTPDestroy:	EXEC @ErrCode = sys.sp_OADestroy @OLEHTTP
	END
	-- Вывод ошибок
	IF (@ErrSource IS NOT NULL)
		IF (@@OutError = 1) BEGIN
			SELECT	 @@Header	= (SELECT @ErrSource	FOR XML Path(''),Type)
				,@@Body		= (SELECT @ErrDescript	FOR XML Path(''),Type)
			RETURN	1
		END ELSE BEGIN
			RAISERROR('Ошибка при выполнении метода "%s" в "%s": %s',18,1,@ErrMethod,@ErrSource,@ErrDescript)
			RETURN	@@Error
		END
	ELSE	RETURN	0;
END
GO
Можно ещё сэкономить на спичках.
19 апр 11, 10:26    [10534622]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Дополнительная проверка ответа:
+ spSOAPMethodCall
ALTER PROCEDURE [dbo].[spSOAPMethodCall] (
	 @@URL		SysName
	,@@Header	XML	= NULL	OUTPUT
	,@@Body		XML	= NULL	OUTPUT
	,@@TimeOut	Int	= 900000
	,@@OutError	Bit	= 0
) WITH EXECUTE AS 'dbo' AS BEGIN
	-- Для установки Proxy воспользуйтесь "proxycfg -u"
	DECLARE	 @OLEHTTP	Int
		,@HTTPStatus	Int
		,@ErrCode	Int
		,@ErrMethod	SysName
		,@ErrSource	SysName
		,@ErrDescript	NVarChar(4000)
		,@SOAPAction	SysName
		,@Length	Int
		,@Request	XML
		,@Response	XML

	-- OLE HTTPRequest
	EXEC @ErrCode = sys.sp_OACreate 'MSXML2.ServerXMLHTTP' ,@OLEHTTP OUT
	IF (@ErrCode != 0)
		SELECT	 @ErrMethod	= 'sp_OACreate'
			,@ErrSource	= 'MSXML2.ServerXMLHTTP'
			,@ErrDescript	= 'Ошибка создания OLE объекта'
	ELSE BEGIN
		-- Генерация SOAP запроса
		;WITH XMLNAMESPACES (
			 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
			,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
			,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
		SELECT	 @SOAPAction	= CASE	WHEN xmlns LIKE '%/'
						THEN xmlns       + method
						ELSE xmlns + '/' + method
						END
			,@Request	= (
		SELECT	 @@Header	AS [soap:Header]
			,@@Body		AS [soap:Body]
		FOR	XML Path('soap:Envelope'),Type)
		FROM	(SELECT	 @@Body.value('namespace-uri(/*[1])','SysName')
				,@@Body.value('local-name(/*[1])'   ,'SysName')) S(xmlns,method)
		-- Установка TimeOut, HTTTP параметров, запрос
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'setTimeouts'		,NULL ,5000 ,60000 , 30000, @@TimeOut			IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setTimeouts'		GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'open'		,NULL ,'POST' ,@@URL ,'false'				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'open'		GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'setRequestHeader'	,NULL ,'Content-Type'	,'text/xml; charset=utf-8'	IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'setRequestHeader'	,NULL ,'SOAPAction'	,@SOAPAction			IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'setRequestHeader'	GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'send'		,NULL ,@Request						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'send'		GOTO HTTPError END
		-- Проверка HTTP ответа
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'getResponseHeader' ,@ErrDescript	OUT ,'Content-Type'			IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'getResponseHeader'	GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAMethod @OLEHTTP ,'getResponseHeader' ,@Length		OUT ,'Content-Length'			IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'getResponseHeader'	GOTO HTTPError END
		EXEC @ErrCode = sys.sp_OAGetProperty @OLEHTTP ,'status' ,@HTTPStatus OUT						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'status'		GOTO HTTPError END
		IF (@HTTPStatus IN (200,500)) AND (@ErrDescript = 'text/xml; charset=utf-8') BEGIN
			IF (@Length > 4000) BEGIN	-- Не умещается в переменную
				DECLARE	@TResponse TABLE (Response NVarChar(max))
				SET TEXTSIZE 2147483647;-- Используем глючный вариант
				INSERT @TResponse
				EXEC @ErrCode = sys.sp_OAGetProperty @OLEHTTP ,'responseText'						IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'responseText'	GOTO HTTPError END
				SELECT @Response = Convert(XML,Stuff(Response    ,1,IsNull(NullIf(CharIndex('?>',Response    ),0)+1,0),'')) FROM @TResponse
			END ELSE BEGIN			-- Умещается в переменную
				EXEC @ErrCode = sys.sp_OAGetProperty @OLEHTTP ,'responseText' ,@ErrDescript OUT				IF (@ErrCode != 0) BEGIN SET @ErrMethod = 'responseText'	GOTO HTTPError END
				SELECT @Response = Convert(XML,Stuff(@ErrDescript,1,IsNull(NullIf(CharIndex('?>',@ErrDescript),0)+1,0),''))
			END
			-- Парсирование SOAP ответа
			;WITH XMLNAMESPACES (
				 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
				,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
				,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
			SELECT	 @@Header	= R.Response.query('/soap:Envelope/soap:Header/node()')
				,@@Body		= R.Response.query('/soap:Envelope/soap:Body/node()')
			FROM	(SELECT @Response)R(Response)
				-- Парсирование SOAP ошибки
		IF (@HTTPStatus = 500)
			WITH XMLNAMESPACES (
				 'http://www.w3.org/2001/XMLSchema-instance'	AS [xsi]
				,'http://www.w3.org/2001/XMLSchema'		AS [xsd]
				,'http://schemas.xmlsoap.org/soap/envelope/'	AS [soap])
			SELECT	 @ErrMethod	= @SOAPAction
				,@ErrSource	= Coalesce(
						  B.Body.value('(/soap:Fault/faultactor)[1]'	,'SysName')
						 ,B.Body.value('(/soap:Fault/faultcode)[1]'	,'SysName')
						 ,'soap:Server')
				,@ErrDescript	= IsNull(
						  B.Body.value('(/soap:Fault/faultstring)[1]'	,'NVarChar(4000)')
						+ IsNull(
						  B.Body.value('(/soap:Fault/detail)[1]'	,'NVarChar(4000)')
						 ,''),'Unknown Error')
			FROM	(SELECT @@Body)	  B(Body)
		END ELSE
			SELECT	 @ErrMethod	= 'send'
				,@ErrSource	= 'soap:Client'
				,@ErrDescript	= 'Сервер недоступен (' + Convert(VarChar,@HTTPStatus) + ': ' + @ErrDescript + ')'
		-- Уничтожение HTTPRequest
		GOTO HTTPDestroy
		HTTPError:	EXEC @ErrCode = sys.sp_OAGetErrorInfo @OLEHTTP ,@ErrSource OUT ,@ErrDescript OUT
		HTTPDestroy:	EXEC @ErrCode = sys.sp_OADestroy @OLEHTTP
	END
	-- Вывод ошибок
	IF (@ErrSource IS NOT NULL)
		IF (@@OutError = 1) BEGIN
			SELECT	 @@Header	= (SELECT @ErrSource	FOR XML Path(''),Type)
				,@@Body		= (SELECT @ErrDescript	FOR XML Path(''),Type)
			RETURN	1
		END ELSE BEGIN
			RAISERROR('Ошибка при выполнении метода "%s" (%s): %s',18,1,@ErrMethod,@ErrSource,@ErrDescript)
			RETURN	@@Error
		END
	ELSE	RETURN	0;
END
GO
9 июн 11, 16:03    [10790660]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Ворон743
Guest
Коллеги, а что делать, если веб-сервис возвращает не xml, а html с кодировкой windows-1251 (http-equiv="Content-Type" content="text/html; charset=windows-1251")? Как его обработать?
21 ноя 11, 12:52    [11631054]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Ворон743, там не даром стоит
ErrDescript = 'text/xml; charset=utf-8'
Вы то сами зайдите через брузер и воотчию убедитесь что WS лежит.

А SOAP протокол основан на XML. Может у нас не Web сервис, а просто HTTP запрос (POST/GET)?
21 ноя 11, 14:10    [11631859]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Mnior
А SOAP протокол основан на XML. Может у вас не Web сервис, а просто HTTP запрос (POST/GET)?
21 ноя 11, 14:12    [11631875]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
juwdoks
Member

Откуда:
Сообщений: 144
Сейчас есть решения для SOAP и REST, а для XML-RPC есть какие-то примеры? Как с таким вебсервисом поработать напрямую из кода TSQL? Через clr?
16 июл 12, 11:47    [12871709]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Поменять десять строк, делов-то. Спеки то есть. Даже у Вики есть страничка.

Или вы не хотите включить голову и понять смысл вышеописанного кода?
16 июл 12, 13:17    [12872260]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
juwdoks
Member

Откуда:
Сообщений: 144
Mnior,

Как всегда, не в бровь, а в глаз :)
И на том спасибо, допилю как подсказано.
16 июл 12, 13:40    [12872350]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
juwdoks
Member

Откуда:
Сообщений: 144
Не могу понять что не так: открываю соединение, объявляю Content-Type, отправляю запрос, но все время получаю ответ, что мой xml с параметрами неправильный.
Проверял через форму - если тот же xml запроса отправить просто post_ом, то все хорошо, а от MSSQL этот запрос доходит до скрипта без строки <?xml version="1.0" encoding="UTF-8"?> - на что и ругается вебсервис (похоже).
Проблема в XML declaration - как заставить MSSQL не убирать его из запроса, даже если version="1.0"?
17 июл 12, 10:03    [12876080]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
juwdoks, согласен, тотальное большинство не знают что такое XML декларация и для чего она.
Кстати, тот сервер, который вы используете писали и...ты. Кодировка текстового потока задаётся в заголовках. Этого достаточно.
Когда же уже вытестится эта "проблема".

juwdoks, в XML нет никаких заголовков, они есть в средствах хранения и передачи данных.
Если их серевер настолько туп, то передавайте строку с дополненной шапкой, а не XML структуру.
17 июл 12, 11:37    [12876660]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Mnior
Когда же уже вытеснится эта "проблема" сдравым кодом.
Хотя чё я, там же допотопный XML-RPC. Другого и ждать нечего.
17 июл 12, 11:40    [12876690]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
juwdoks
Member

Откуда:
Сообщений: 144
Под 2012 даёт ошибку:
Ошибка при выполнении метода "send" (msxml3.dll): Параметр задан неверно.

Причём формат методов объекта MSXML2.ServerXMLHTTP вроде не менялся ((
Кто-то сталкивался? В инете нарыл пару аналогичных жалоб, но решения нет, чтоб его.
3 ноя 14, 12:09    [16792163]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Sandist
Member

Откуда:
Сообщений: 401
juwdoks,

та же беда. Мне нужно то же на 2014 сервере. Кто вообще этим пользуется? или может что новое есть для решение таких задач в 2014 скуле?
21 ноя 17, 14:48    [20972374]     Ответить | Цитировать Сообщить модератору
 Re: Коннектор к веб-службам. MS SQL 2000  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7746
Sandist,

нормальные люди пишут трехслойку в таких случаях, а прочие - CLR процедуры.
21 ноя 17, 15:02    [20972453]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить