从SQL Server存储过程调用API

xsuvu9jc  于 2023-01-29  发布在  SQL Server
关注(0)|答案(9)|浏览(591)

从ASP.NET Web窗体调用API非常容易。

WebClient wc = new WebClient();
string urlData = wc.DownloadString("http://xxx.xxx.xx.xx/sssss/getResponse.do?ID=testing");

但是我们可以从SQL Server存储过程调用API吗?
如果是,那么我们如何从SQL Server存储过程调用API,以及如何获得API响应?

lf5gs5x2

lf5gs5x21#

有关详细信息,请参见a link

Declare @Object as Int;
Declare @ResponseText as Varchar(8000);

Code Snippet
Exec sp_OACreate 'MSXML2.XMLHTTP', @Object OUT;
Exec sp_OAMethod @Object, 'open', NULL, 'get',
                 'http://www.webservicex.com/stockquote.asmx/GetQuote?symbol=MSFT', --Your Web Service Url (invoked)
                 'false'
Exec sp_OAMethod @Object, 'send'
Exec sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT

Select @ResponseText

Exec sp_OADestroy @Object
uoifb46i

uoifb46i2#

我做了这么多,我希望我的努力能帮助你。
只需将其粘贴到SSMS中并按F5:

Declare @Object as Int;
DECLARE @hr  int
Declare @json as table(Json_Table nvarchar(max))

Exec @hr=sp_OACreate 'MSXML2.ServerXMLHTTP.6.0', @Object OUT;
IF @hr <> 0 EXEC sp_OAGetErrorInfo @Object
Exec @hr=sp_OAMethod @Object, 'open', NULL, 'get',
                 'http://overpass-api.de/api/interpreter?data=[out:json];area[name=%22Auckland%22]-%3E.a;(node(area.a)[amenity=cinema];way(area.a)[amenity=cinema];rel(area.a)[amenity=cinema];);out;', --Your Web Service Url (invoked)
                 'false'
IF @hr <> 0 EXEC sp_OAGetErrorInfo @Object
Exec @hr=sp_OAMethod @Object, 'send'
IF @hr <> 0 EXEC sp_OAGetErrorInfo @Object
Exec @hr=sp_OAMethod @Object, 'responseText', @json OUTPUT
IF @hr <> 0 EXEC sp_OAGetErrorInfo @Object

INSERT into @json (Json_Table) exec sp_OAGetProperty @Object, 'responseText'
-- select the JSON string
select * from @json
-- Parse the JSON string
SELECT * FROM OPENJSON((select * from @json), N'$.elements')
WITH (   
      [type] nvarchar(max) N'$.type'   ,
      [id]   nvarchar(max) N'$.id',
      [lat]   nvarchar(max) N'$.lat',
      [lon]   nvarchar(max) N'$.lon',
      [amenity]   nvarchar(max) N'$.tags.amenity',
      [name]   nvarchar(max) N'$.tags.name'     
)
EXEC sp_OADestroy @Object

此查询将为您提供3个结果:

1.在出现错误时捕获错误(不要惊慌,它将始终显示超过4000个字符的错误,因为NVARCHAR(MAX)最多只能存储4000个字符)
2.将JSON放入一个字符串中(这是我们想要的)
3.奖金:解析JSON并将数据很好地存储到表中(这有多酷?)

ewm0tg9j

ewm0tg9j3#

对着虚空尖叫--只是说“不”,别这么做。这是个愚蠢的主意。
与外部数据源集成是SSIS的目的,或者编写一个查询框并进行API调用的. net应用程序/服务。
编写CLR代码以使SQL进程能够调用Web服务是一件如果做得不好就可能使SQL机器屈服的事情-想象一下,将CLR函数放在某个视图中-后来有人不知道你做了什么,并在该视图上连接了一百万行的表-突然之间,你的SQL机器正在进行一百万个单独的Web API调用。
整个想法太疯狂了。
这种做法是企业DBA不信任开发人员的原因。
CLR是一种巨大的力量,它带来巨大的责任,而以上是对它的滥用。

kqlmhetl

kqlmhetl4#

我认为使用CLR存储过程SQL-APIConsumer会更容易:

exec [dbo].[APICaller_POST]
     @URL = 'http://localhost:5000/api/auth/login'
    ,@BodyJson = '{"Username":"gdiaz","Password":"password"}'

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

cl25kdpy

cl25kdpy5#

免责声明:我为ZappySys(为SQL Server等应用程序制作API驱动程序的公司)工作
在SQL Server存储过程中调用API可以通过以下3种方式完成(至少根据我所知)。每种方法都有自己的优点和缺点,所以请根据您的需要选择它。

方法-1(使用sp_OAxxx)

使用sp_OA方法(如Francesco Mantovani所述)

    • 优点**
  • 无需额外编程,如方法2中建议的SQL CLR方法
    • 缺点**
  • 调用sp_OAxxx procs被认为是高度不安全的方法,不建议作为per this SO Post使用。
  • 默认情况下,只有管理员组可以执行此过程

METHOD-2(代码自定义CLR程序)

使用CLR存储过程(如Geraldo Diaz所述)

    • 优点**
  • 您可以使用任何. net语言(如C #/www.example.com)编写高度自定义的逻辑来调用APIVB.net)
    • 缺点**
  • 需要编程知识
  • 注册自定义CLR dll和configure CLR security需要其他步骤

方法-3(使用第三方API驱动程序)

您可以使用第三方API驱动程序和call REST API in SQL Server like this way(链接服务器+OPENQUERY)-请参见下图中存储过程中的API数据加载示例。

    • 优点**
  • 无需学习自定义编程来编写自己的dll
  • 无需在SQL Server上取消阻止/配置其他安全性(与方法1和2不同)
    • 缺点**
  • 非免费解决方案(需要购买驱动程序)

lnvxswe2

lnvxswe26#

简单的SQL触发API调用,无需构建代码项目
我知道这远非完美或体系结构的纯粹,但我有一个客户在短期内迫切需要通过不成熟的API与第三方产品集成(没有WSDL)我基本上需要在数据库事件发生时调用API。我被给予了基本的调用信息- URL、方法、数据元素和令牌,但是没有WSDL或其他开始导入到代码项目中。所有的建议和解决方案似乎都是从导入开始的。
我用了ARC(高级Rest客户端)Chrome扩展和JaSON来测试浏览器与服务的交互,并优化调用。这给了我经过测试的原始调用结构和响应,让我可以快速使用API。从那里开始,我开始尝试使用在线转换从JSON生成wsdl或xsd,但认为这将花费太长时间才能开始工作,所以我找到了cURL(云部分,音乐播放). cURL允许我将API调用从任何地方发送到本地管理器。然后,我打破了一些设计规则,构建了一个触发器,将DB事件和SQL存储过程排队,并调度任务将参数传递到cURL并进行调用。最初,我让触发器调用XP_CMDShell(我知道,嘘),但不喜欢事务性暗示或安全问题,所以切换到存储过程方法。
最后,匹配API调用用例的DB插入触发器写入队列表,参数用于API调用存储过程每5秒运行一次,运行Cursor以提取每个队列表条目,将XP_CMDShell调用发送到带参数的bat文件,Bat文件包含Curl调用,带插入的参数,将输出发送到日志。运行良好。
同样,并不完美,但对于一个紧凑的时间轴,和一个系统使用短期,并可以密切监测,以应对连接和不可预见的问题,它的工作。
希望这能帮助那些在有限的API信息中挣扎的人快速获得解决方案。

whitzsjs

whitzsjs7#

我建议使用CLR用户定义函数,如果你已经知道如何用C#编程,那么代码应该是;

using System.Data.SqlTypes;
using System.Net;

public partial class UserDefinedFunctions
{
 [Microsoft.SqlServer.Server.SqlFunction]
 public static SqlString http(SqlString url)
 {
  var wc = new WebClient();
  var html = wc.DownloadString(url.Value);
  return new SqlString (html);
 }
}

这是安装说明https://blog.dotnetframework.org/2019/09/17/make-a-http-request-from-sqlserver-using-a-clr-udf/

pod7payv

pod7payv8#

SQL查询select * from openjson ...仅适用于SQL版本2016及更高版本。需要SQL兼容模式130。

pxyaymoc

pxyaymoc9#

今天,有了新引入的系统存储过程sp_invoke_external_rest_endpoint,可以更轻松地从Azure SQL数据库调用REST端点(将来会支持SQL Server和Azure SQL MI):
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-invoke-external-rest-endpoint-transact-sql
例如:

DECLARE @ret INT, @response NVARCHAR(MAX);

EXEC @ret = sp_invoke_external_rest_endpoint
  @url = N'https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?key1=value1',
  @headers = N'{"header1":"value_a", "header2":"value2", "header1":"value_b"}',
  @payload = N'{"some":{"data":"here"}}',
  @response = @response OUTPUT;

SELECT @ret AS ReturnCode, @response AS Response;

相关问题