【问题标题】:Send json value in SP_OAMETHOD在 SP_OAMETHOD 中发送 json 值
【发布时间】:2021-05-03 12:45:58
【问题描述】:

我尝试使用 SQL Server 存储过程中的 json 值调用 web api post 方法。

我正在尝试以下代码,但发送失败。我收到以下错误

代码“-2147012851”

代码:

EXEC sp_OACreate 'MSXML2.ServerXMLHTTP', @Object OUT;
EXEC sp_OAMethod @Object, 'open', NULL, 'post',
                 'http://xx.xxx.xx.xx/Test_API/Notification/SendTestProperties', --Your Web Service Url (invoked)
                 'false'
EXEC sp_OAMethod @Object, 'setRequestHeader', NULL, 'Content-Type', 'application/json'

EXEC @Result = sp_OAMethod @Object, 'send', NULL, @body

EXEC sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT

EXEC sp_OADestroy @Object

【问题讨论】:

  • 这真的不是 SQL Server 的工作;您应该在应用程序中处理此类任务。
  • 但我的项目需要这种方式@larnu。帮我解决这个问题
  • 为什么您的项目要求您使用那些非常古老的程序?由于历史原因,它们实际上仍然存在。如果您必须从 SQL Server 调用 API,那么创建和使用自己的 CLR 过程可能会好得多。
  • sp_OAMethod 和朋友是遗留问题:他们有很多问题,难以编码,难以调试。您似乎正在尝试下载 HTTP 请求:为此使用 Powershell 或 C#,它们更适合。您可以将 PS 脚本编写为 SQL 代理作业,并使用sp_start_job从 SQL 执行它

标签: sql json sql-server rest post


【解决方案1】:

XMLHTTP 上有一个ResponseText 属性,您不能使用sp_OAMethod 来检索它,但您必须改用sp_OAGetProperty

不幸的是,如果值变得太大,您仍然不能将输出参数与sp_OAGetProperty 存储过程一起使用,而是必须使用临时表来检索它的值,像这样

DECLARE     @TmpGetProperty TABLE(Value NVARCHAR(MAX))

INSERT      @TmpGetProperty
EXEC        @Result = dbo.sp_OAGetProperty @Object, 'ResponseText'
IF          @Result <> 0 GOTO ErrorFound

完整的工作示例

IF OBJECT_ID('usp_sys_InvokeWebService') IS NOT NULL DROP PROC usp_sys_InvokeWebService
GO
/*
DECLARE @Result INT, @Status INT, @StatusText VARCHAR(100), @ResponseText NVARCHAR(MAX)
EXEC    @Result = dbo.usp_sys_InvokeWebService 'GET', 'http://api.sample.com/test/ial_ses/ial/sespa/pharma/', @Timeout = 5
                        , @Status = @Status OUTPUT, @StatusText = @StatusText OUTPUT, @ResponseText = @ResponseText OUTPUT
SELECT  @Result AS Result, @Status AS Status, @StatusText AS StatusText, @ResponseText AS ResponseText


DECLARE @Result INT, @Status INT, @StatusText VARCHAR(100), @PostData NVARCHAR(MAX)
SELECT  @PostData = '{ your JSON here }'
EXEC    @Result = dbo.usp_sys_InvokeWebService 'POST', 'http://api.sample.com/test/ial_ses/sespa/trn/', @Timeout = 5
                        , @PostData=@PostData, @Status = @Status OUTPUT, @StatusText = @StatusText OUTPUT
SELECT  @Result AS Result, @Status AS Status, @StatusText AS StatusText
*/

CREATE PROC usp_sys_InvokeWebService(
            @Verb           VARCHAR(100)
            , @Url          VARCHAR(1000)
            , @AuthHeader   VARCHAR(100)    = NULL
            , @ContentType  VARCHAR(100)    = NULL
            , @Accept       VARCHAR(100)    = NULL
            , @PostData     NVARCHAR(MAX)   = NULL
            , @Timeout      FLOAT           = NULL          -- in seconds
            , @NoRaiseError BIT             = 0
            , @Status       INT             = NULL OUTPUT 
            , @StatusText   VARCHAR(100)    = NULL OUTPUT 
            , @ResponseText NVARCHAR(MAX)   = NULL OUTPUT 
) WITH EXECUTE AS OWNER AS
/*------------------------------------------------------------------------

    Invoke web service endpoint

*/------------------------------------------------------------------------
SET         NOCOUNT ON

DECLARE     @RetVal         INT
            , @HObj         INT
            , @HResult      INT
            , @TimeoutMs    INT
            , @ErrSource    VARCHAR(255)
            , @ErrDescription VARCHAR(1000)

DECLARE     @TmpGetProperty TABLE(Value NVARCHAR(MAX))

--- init local vars and param defaults
SELECT      @RetVal = 0
            , @ContentType = COALESCE(@ContentType, CASE WHEN @PostData IS NOT NULL THEN 'application/json' END)
            , @TimeoutMs = @Timeout * 1000

BEGIN TRY
            IF          SUSER_NAME() <> 'sa' EXECUTE AS LOGIN = 'sa'

            EXEC        @HResult = dbo.sp_OACreate 'MSXML2.ServerXMLHTTP', @HObj OUTPUT
            IF          @HResult <> 0 GOTO QH

            IF          @TimeoutMs IS NOT NULL
            BEGIN
                        --- resolveTimeout, connectTimeout, sendTimeout, receiveTimeout
                        EXEC        @HResult = dbo.sp_OAMethod @HObj, 'SetTimeouts', NULL, 5000, 5000, @TimeoutMs, @TimeoutMs
                        IF          @HResult <> 0 GOTO QH
            END

            IF          @Status IS NOT NULL
            BEGIN
                        --- ignore server certificate errors
                        EXEC        @HResult = dbo.sp_OAMethod @HObj, 'SetOption', NULL, 2, 13056
                        IF          @HResult <> 0 GOTO QH
            END

            EXEC        @HResult = dbo.sp_OAMethod @HObj, 'Open', NULL, @Verb, @Url, 0 -- Async:=False
            IF          @HResult <> 0 GOTO QH

            IF          @AuthHeader IS NOT NULL
            BEGIN
                        EXEC        @HResult = dbo.sp_OAMethod @HObj, 'SetRequestHeader', NULL, 'Authorization', @AuthHeader 
                        IF          @HResult <> 0 GOTO QH
            END

            IF          @ContentType IS NOT NULL
            BEGIN
                        EXEC        @HResult = dbo.sp_OAMethod @HObj, 'SetRequestHeader', NULL, 'Content-Type', @ContentType
                        IF          @HResult <> 0 GOTO QH
            END

            IF          @Accept IS NOT NULL
            BEGIN
                        EXEC        @HResult = dbo.sp_OAMethod @HObj, 'SetRequestHeader', NULL, 'Accept', @Accept
                        IF          @HResult <> 0 GOTO QH
            END

            IF          @PostData IS NOT NULL
            BEGIN
                        EXEC        @HResult = dbo.sp_OAMethod @HObj, 'Send', NULL, @PostData
                        IF          @HResult <> 0 GOTO QH
            END
            ELSE BEGIN
                        EXEC        @HResult = dbo.sp_OAMethod @HObj, 'Send'
                        IF          @HResult <> 0 GOTO QH
            END

            EXEC        @HResult = dbo.sp_OAGetProperty @HObj, 'Status', @Status OUTPUT
            IF          @HResult <> 0 GOTO QH

            EXEC        @HResult = dbo.sp_OAGetProperty @HObj, 'StatusText', @StatusText OUTPUT
            IF          @HResult <> 0 GOTO QH

            INSERT      @TmpGetProperty
            EXEC        @HResult = dbo.sp_OAGetProperty @HObj, 'ResponseText'
            IF          @HResult <> 0 GOTO QH

            SELECT      TOP 1 @ResponseText = Value
            FROM        @TmpGetProperty
END TRY
BEGIN CATCH
            SELECT      @ErrSource = CONVERT(VARCHAR(50), ERROR_LINE())
                        , @ErrDescription = RTRIM(REPLACE(ERROR_MESSAGE(), CHAR(13) + CHAR(10), ' '))

            SELECT      @RetVal = 1
                        , @StatusText = @ErrDescription

            IF          COALESCE(@NoRaiseError, 0) = 0
            BEGIN
                        RAISERROR   ('Error on line %s: %s', 16, 1, @ErrSource, @ErrDescription)
            END
END CATCH

QH:
IF          @HResult <> 0
BEGIN
            SELECT      @RetVal = 1
                        , @StatusText = CONVERT(VARCHAR(50), CONVERT(BINARY(4), @HResult), 1)

            IF          COALESCE(@NoRaiseError, 0) = 0
            BEGIN
                        EXEC        dbo.sp_OAGetErrorInfo @HObj, @ErrSource OUTPUT, @ErrDescription OUTPUT
                        
                        SELECT      @ErrDescription = RTRIM(REPLACE(@ErrDescription, CHAR(13) + CHAR(10), ' '))

                        RAISERROR   ('Error in %s: %s (0x%08X)', 16, 1, @ErrSource, @ErrDescription, @HResult)
            END
END

IF          @HObj IS NOT NULL
BEGIN
            EXEC        dbo.sp_OADestroy @HObj
            SET         @HObj = NULL
END

RETURN      @RetVal

您可以在@Status out 参数中使用非NULL 值来忽略服务器证书错误。

【讨论】:

  • 我收到证书颁发机构错误“证书颁发机构无效或不正确 (0x80072F0D)”
  • 刚刚更新了存储过程。您可以在@Status 输出参数(例如@Status=0)中使用非NULL 值来忽略服务器证书错误。
猜你喜欢
  • 1970-01-01
  • 2011-09-29
  • 1970-01-01
  • 2019-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
  • 2018-07-16
相关资源
最近更新 更多