我正在整理一个简单的 Python 脚本,利用 SQL Server 中的 Python 机器学习服务功能。目标是我的 SQL 服务器可以使用 python 脚本 ping 外部 API 并将结果读入变量。
我已经成功构建了 GET 请求,我只是在努力将 API 的输出反馈到数据库中
到目前为止我所拥有的:
EXECUTE sp_execute_external_script @language = N'Python',
@script = N'
import requests
import pandas as pd
URL = "https://api.website.io/verify?email=dave@davidson.com&apikey=test_44fbcce85ba0f270273f4452bea2311de50f9c"
r = requests.get(url = URL)
data = r.text
print(data)
'
, @input_data_1 = N''
WITH RESULT SETS(([Col1] varchar(MAX) NOT NULL));
所以 print(data) 在 SSMS 中给了我以下输出:
{"success":false,"message":"Invalid API key"}
但是我不想打印它,我想将它读入SQL。 我并不在乎它是如何产生的,所以现在我只指定了一个名为“Col1”的列来保存输出,但我最终需要将“False”和“Invalid API key”加载到两个变量中我的 SQL Server 存储过程,以便我可以在下一步中使用这些值。如果我必须手动从 JSON 中解析它们,那么我可以接受,但理想情况下,它们会在 SQL 输出中作为单独的列出现。
我已经尝试在各种排列中使用 r.json() 但我遇到了很多不同的错误:
对于 SQL Server 机器学习,我知道我需要创建一个名为“OutputDataSet”的变量,并且该变量的类型需要为“pandas dataframe”,因此我需要将“r”中保存的 JSON 数据转换为熊猫数据框。然而,我在这方面尝试的一切都给了我神秘的错误代码
例如:
OutputDataSet = pd.DataFrame.from_dict(r.json(), orient="index")
给出:“执行错误。”
或
OutputDataSet = pd.DataFrame.from_dict(r.text, orient="index")
给出“AttributeError:'str'对象没有属性'values'”
这是将 JSON 转换为我没有得到的 DataFrame 的语法吗? 或者是否需要额外的步骤或库来将 Requests 库的输出转换为 Pandas 库可以接受的内容?
答案 0 :(得分:0)
经过多次反复试验,我找到了一个有效的解决方案:
我的数据库中有一个 InputData 表,我的存储过程从 InputData 读取所有行,使用 Python 通过 API 运行它们,然后将 API 结果返回到一个临时表中,我可以像使用任何表一样使用它SQL。
在我的“InputData”表中,我有以下列:
参考 - 我公司的专有参考编号,因此我可以知道此 API 数据与哪条公司记录相关。
APIURL - 我的 API 请求的预配置 URL。此字段包含此参考的 API 请求的所有参数,以及此 API 的 API 密钥。基本上整个 HTTP API 请求都在这里。我在前面的 SQL 步骤中创建了这个 URL,因为我用 Python 来做这件事很尴尬,而且在这种情况下没有真正的必要。
JSONDATA - 数据类型为 nvarchar(MAX) 的空列,该列中的所有记录均为 NULL。有点作弊的方式来做到这一点。通过将此 NULL 值作为输入数据中的列传递,我们不必在输出数据中指定或命名它。由于 SQL 表中有一个空列几乎没有区别,因此我选择了这种方式来简化将输出数据从 Python 导出到 SQL 中。
-- Define query
DECLARE @sqlscript NVARCHAR(MAX);
SET @sqlscript = N'SELECT Reference, APIURL, JSONData FROM dbo.InputData';
-- Define Python script
DECLARE @pscript NVARCHAR(MAX);
SET @pscript = N'
import requests # Import the "requests" library that contains the requests.get command we will use to query the API (supports SSL, https etc)
InputDF = InputDataSet # Assign the input data (named InputDataSet by default in SQL Python) to a Python dataframe object named "InputDF"
OutputDF = InputDF # Copy all the input data to a new Python dataframe object named "OutputDF"
for row in InputDF.itertuples(): # Start a loop which iterates over every row in InputDF, using "itertuples" Python function
URL = row.KickBoxURL # Read the KickBox API URL for this case/email address from the input dataframe
r = requests.get(url = URL) # Use the "get" command from the requests library to send our request to the API using that URL
OutputDF.at[row.Index,4]= r.text # Update column 4 (JSONData) of the output dataframe for the current iteruples row index, with the output JSON text from the .get command (stored in "r")
OutputDataSet = OutputDF # Return the OutputDF dataset as a SQL Server "OutputDataSet" (the default name in SQL Python) which returns the data as a query output, which we will INSERT into #Results
';
-- Declare temp table to hold results
DROP TABLE IF EXISTS #Results
CREATE TABLE #Results (Reference varchar(10) NOT NULL PRIMARY KEY CLUSTERED,
APIURL varchar(1000) NOT NULL,
JSONOutput nvarchar(MAX) NULL)
-- Run procedure using Python script and T-SQL query and Insert results to #Results
INSERT #Results
EXEC sp_execute_external_script
@language = N'Python',
@script = @pscript,
@input_data_1 = @sqlscript;
在运行上述程序后,我现在有一个名为 #Results 的临时表,其中包含我发送的每个请求的所有参考编号和来自 API 的响应 JSON。
然后我可以对该临时表执行一些 JSON 查询,以从包含我需要的数据的 JSON 中提取特定字段。由于那时我不再查询 API,我现在可以根据需要执行任意数量的 SELECT 查询,但我每条记录只访问一次外部 API。