【问题标题】:Can SQL Server send a web request?SQL Server 可以发送 Web 请求吗?
【发布时间】:2011-05-12 19:46:43
【问题描述】:

我在本地网络上有一个 SQL Server 数据库和一个 Intranet Web 应用程序。 Intranet Web 应用程序创建记录并将它们发送到数据库。我有一个 Internet Web 应用程序,我想使用本地网络上的 SQL Server 数据库发送新记录。

由于各种原因,我无法更改/修改 Intranet Web 应用程序,因此我唯一的选择是在本地 SQL Server 上创建一个触发器,该触发器将使用某种 http post 请求将新记录发送到 Internet Web 应用程序或url调用。

INTERNET Web 应用程序设置有 RESTful api,可以通过表单发布到可公开访问的 url(例如http://www.example.com/records/new)接收新记录。

有谁知道在 SQL Server 中是否可以通过 url 发送数据(xml、json、url 中的普通变量)?

感谢您的任何想法!

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql


    【解决方案1】:

    这是可能的,但在现实世界中比您想象的幼稚方法要复杂一些。首先,让触发器等待 HTTP 请求是不可接受的:

    • 首先,您的应用程序将爬到一个急刹车,因为触发器会阻塞资源(主要是锁)等待来自某个遥远的 WWW 服务的响应。
    • 第二个更微妙但更糟糕的是,存在回滚时的正确性问题。如果向 HTTP 请求发出的事务回滚,则无法“撤消”HTTP 请求。

    解决方案是通过队列将触发器与 HTTP 请求解耦。触发器将请求排入本地队列并提交,而单独的处理部分将这些请求出列并发出 HTTP 请求。这解决了上面指出的两个问题。队列可以使用普通表(参见Using Tables as Queues),也可以使用Service Broker,两者都很好。

    现在关于如何使这些请求出列并实际发出 HTTP 调用,我强烈建议使用专用进程(即专用于此目的的应用程序)。虽然可以使用 SQLCLR,但这是一个非常糟糕的选择。 SQL Server 资源(特别是 workers)在等待 Internet 响应时浪费得非常宝贵。

    【讨论】:

    • 我不是在等待 http 请求。我希望触发器启动 http 请求。我希望触发器在更新新记录时调用 url。我不需要它来等待响应或类似的事情
    • 但该触发器将等待 http 请求。触发器将在插入/更新时执行,只有当触发器完成执行时,插入/更新才会完成并“完成”插入/更新过程。这一切都是同步发生的。触发器应尽可能小且尽可能快。尽可能不要使用触发器,除非将审计类型的数据转储到另一个表。
    • 在过去 10 年中,关于 SQL CLR 的最后一条建议有什么变化吗?
    【解决方案2】:

    作为一个很好的(相当可靠和可扩展的)选项,您可以使用SQL CLR 与 Web 应用程序/Web 服务进行交互。

    例如,搜索“SQL CLR WebRequest”或“SQL CLR WCF”。

    【讨论】:

    • 或 SSIS - 集成服务。
    • @marc_s:根据我不太深入的经验,SSIS 比 SQLCLR 更复杂
    • @marc_s 同样使用 SSIS,您最终还是不得不编写 C#,因为它通常不够灵活。
    【解决方案3】:

    先做后续

    sp_configure 'show advanced options', 1;
    go
    RECONFIGURE;
    go
    GO
    sp_configure 'Ole Automation Procedures', 1;
    GO
    RECONFIGURE;
    GO
    

    然后创建一个函数

    create function GetHttp
    (
        @url varchar(8000)      
    )
    returns varchar(8000)
    as
    BEGIN
        DECLARE @win int 
        DECLARE @hr  int 
        DECLARE @text varchar(8000)
    
        EXEC @hr=sp_OACreate 'WinHttp.WinHttpRequest.5.1',@win OUT 
        IF @hr <> 0 EXEC sp_OAGetErrorInfo @win
    
        EXEC @hr=sp_OAMethod @win, 'Open',NULL,'GET',@url,'false'
        IF @hr <> 0 EXEC sp_OAGetErrorInfo @win
    
        EXEC @hr=sp_OAMethod @win,'Send'
        IF @hr <> 0 EXEC sp_OAGetErrorInfo @win
    
        EXEC @hr=sp_OAGetProperty @win,'ResponseText',@text OUTPUT
        IF @hr <> 0 EXEC sp_OAGetErrorInfo @win
    
        EXEC @hr=sp_OADestroy @win 
        IF @hr <> 0 EXEC sp_OAGetErrorInfo @win 
    
        RETURN @text
    END
    

    像这样使用:

    select dbo.GetHttp('http://127.0.0.1/mywebpage.php')
    

    【讨论】:

      【解决方案4】:

      您可以尝试使用此 CLR 存储过程SQL-APIConsumer

      它有多个过程,允许您调用只需要一个参数甚至传递多个标头和令牌身份验证的简单 API。

      【讨论】:

        猜你喜欢
        • 2012-09-16
        • 2012-12-17
        • 1970-01-01
        • 2015-03-21
        • 2018-05-31
        • 2012-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多