Introduction
Please visit this page to see all Pre-Configured ready to use API connectors which you can use in SSIS API Source / SSIS API Destination OR API ODBC Driver (for non-SSIS Apps such as Excel, Power BI, Informatica).
In our previous blog post we saw how to import rest API in SQL Server. Using same concepts lets look at how to import Amazon MWS Data into SQL Server. We will explore many techniques to call Amazon MWS API and learn how to automate Amazon MWS data extraction without doing any ETL. We will call MWS XML or CSV API just using T-SQL code. We will also learn how to Download Reports from by calling MWS API.
You can also refer other articles here (Power BI) and here (SSIS)
Requirements
This article talks about few tools and techniques in order to load API data in SQL Server. Please make sure following prerequisites are met.- Download and Install ZappySys ODBC PowerPack (This includes XML / JSON / REST API and few other drivers for SQL Server and ODBC connectivity in tools like Excel, Power BI, SSRS)
- Make sure you have access to SQL Server Instance. If you cant find one still want to try what is mentioned in this article then install FREE SQL Express Edition
- Confirm that you have SSMS Installed. If you don't have then you can download from here.
About Amazon MWS API
If you want to sell something on Amazon you can use their e-commerce platform with some monthly fee. You can setup your entire online store / inventory using admin interface.
Amazon Marketplace Web Service (Amazon MWS) is an integrated web service API that helps Amazon sellers to programmatically exchange data on listings, orders, payments, reports, and more. Using these API you can read or write data from your Seller account and integrate it inside your own Systems (e.g. Reporting / ETL / BI tools).
Obtain MWS API Access Key / Secret and Seller ID
Very first thing to call any MWS API is to obtain Access Key, Secret Key and Seller ID (i.e. Merchant ID). To obtain this you first have to register a developer.
Here is where to look for your Merchant ID and Key / Secret. Here is direct link to User Permissions page.
Getting Started
Now let’s look at step by step instructions on how to call Amazon MWS API and then import into Power BI. In below steps we will use ZappySys ODBC PowerPack so make sure it’s installed first.
Using ScratchPad to Test Amazon MWS API
Each MWS API has set of required and optional parameters. You can refer each API page for details. For example ListMatchingProducts API which we will use as an example. To make MWS API testing / learning easy, Amazon provides online testing tool called MWS ScratchPad. We will use this tool to craft API requests and use that information in ODBC driver SQL queries and later import data in Power BI.
- Open MWS ScratchPad by vising https://mws.amazonservices.com/scratchpad/index.html
- Select Products API category and pick ListMatchingProducts API
- Enter your SellerID (i.e. Merchant ID), Developer AccessKey (i.e. AWSAccessKeyId) and Secret Key we obtained in the previous section. Enter MarketId (e.g. ATVPDKIKX0DER for USA Market) and other parameters as below and Click Submit to see response.
- Click on the Response Details Tab to extract some important information we will use for ODBC configuration. Notice attributes in red rectangles. They are the ones which we will need in the POST request Body. ZappySys Drivers supply many common parameters automatically but any API endpoint specific parameter must be supplied in the Request Body. For example you dont have to supply SignatureVersion, Timestamp, Signature or SignatureMethod
This API requires Market ID parameter so enter it as per your Market where you selling. For example USA marketplaceid = ATVPDKIKX0DER. You can lookup correct MarketplaceId by checking this help (endpoints / marketplaces).
Setup Amazon MWS API Connections
Configure ZappySys Data Gateway
Now let's look at steps to configure Data Gateway after installation.- Assuming you have installed ZappySys ODBC PowerPack using default options (Which also enables Data Gateway Service)
- Search "Gateway" in your start menu and click ZappySys Data Gateway
- First, make sure Gateway Service is running (Verify Start icon is disabled)
- Also, verify Port on General Tab
- Now go to Users tab. Click Add icon to add a new user. Check Is admin to give access to all data sources you add in future. If you don't check admin then you have to manually configure user permission for each data source.
Create XML Driver Connection for Amazon MWS API (e.g. RequestReport )
Some APIs we need to call in this article is XML format and some API (e.g. GetReport) is CSV format – Tab delimited so we need to create 2 different connections using CSV driver and XML driver. So lets get started with Amazon MWS Connection for XML API.
- Click on Add New Data source. Name as AMAZON-MWS-XML and select Native – ZappySys XML Driver option.
- Now click Edit to Configure Settings. For now we will only care OAuth Connection settings. All other options are overwritten in SQL Query.
- When UI opens for Driver Enter MWS API Service URL as below. Notice that we added /Products/2011-10-01 (This was extracted from previous section). You can check full list of Amazon MWS Endpoints here. Because we are connecting to USA region we will use below URL.
1https://mws.amazonservices.com/Products/2011-10-01 - Select OAuth from the Connection dropdown and Click Configure Settings
- On the Connection UI, Select OAuth Provider Amazon Market Web Service (MWS)
- Enter your API Access Key and Secret Key (obtained from here)
- Your connection will look like below.
- Also configure Retry options to handle API limit reached error when you call API too often. For Amazon MWS we get Status code 503 when request is throttled so lets narrow down on which error we want to retry.
- Click OK to save OAuth Connection UI to go back to main UI
- Now Go to Throttling Tab and enter some delay (e.g. enter 20000 for 20sec delay after each request). This will slow down API calls so we don’t face errors about API Limit reached.
- Click OK to Save UI
- Click Save button on Gateway UI to save and restart
Create CSV Driver Connection for Amazon MWS API (e.g. GetReport )
Now lets create a connection CSV API (e.g. GetReport ).
Follow almost same steps as previous section except use CSV Driver when you click on Add new Data source select Native – ZappySys CSV Driver and name data source as AMAZON-MWS-CSV . As we mentioned for now we mostly want to setup Connection and not worry about Request Body, Pagination etc.
Create Linked Server for SQL Server
Run following Script in SSMS to create Linked servers. Change ######## with Your gateway password. Change localhost with machine name or IP where ZappySys Gateway Is running. Use localhost if SQL Server and Gateway both on the same machine.
1 2 3 4 5 6 7 8 9 10 |
USE [master] GO EXEC master.dbo.sp_addlinkedserver @server = N'AMAZON-MWS-XML', @srvproduct=N'', @provider=N'SQLNCLI', @datasrc=N'localhost,5000', @catalog=N'AMAZON-MWS-XML' EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'AMAZON-MWS-XML',@useself=N'False',@locallogin=NULL,@rmtuser=N'tdsuser',@rmtpassword='########' GO EXEC master.dbo.sp_addlinkedserver @server = N'AMAZON-MWS-CSV', @srvproduct=N'', @provider=N'SQLNCLI', @datasrc=N'localhost,5000', @catalog=N'AMAZON-MWS-CSV' EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'AMAZON-MWS-CSV',@useself=N'False',@locallogin=NULL,@rmtuser=N'tdsuser',@rmtpassword='########' GO |
If you want to know how to configure Linked Server using UI then check this article.
Amazon MWS ListOrders Example
Now lets look at how to call ListOrders request with pagination in SQL Server. Create a following Stored Procedure to List MWS Orders. If you want to extract many orders then call Report rather than this proc (See next section for generating reports)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
USE MyDatabase GO /* Example: exec usp_MWS_ListOrders @SellerId='Axxxxxxx', @MarketplaceId ='Bxxxxxxx',@CreatedAfter='2019-01-01' */ Create proc [dbo].[usp_MWS_ListOrders] @SellerId varchar(100), @MarketplaceId varchar(100), @CreatedAfter varchar(100), @CreatedBefore varchar(100)=null, @MaxRows int=0 as declare @sql varchar(max) declare @limitClase varchar(100)='' if(@MaxRows>0) set @limitClase =' LIMIT ' + cast(@MaxRows as varchar(20)) --//Confirm ISO Date format 2019-06-01T04%3A00%3A00Z rather 2019-06-01T04:00:00Z if(isnull(@CreatedAfter,'')<>'') begin set @CreatedAfter='&CreatedAfter=' + @CreatedAfter set @CreatedAfter=replace(@CreatedAfter,':','%3A') if(@CreatedAfter NOT LIKE @CreatedAfter + 'T%') set @CreatedAfter=@CreatedAfter + 'T00%3A00%3A00Z' if(@CreatedAfter NOT LIKE @CreatedAfter + '%Z') set @CreatedAfter=@CreatedAfter + 'Z' --//T04%3A00%3A00Z end if(isnull(@CreatedBefore,'')<>'') begin set @CreatedBefore='&CreatedBefore=' + @CreatedBefore set @CreatedBefore=replace(@CreatedBefore,':','%3A') if(@CreatedBefore NOT LIKE @CreatedBefore + 'T%') set @CreatedBefore=@CreatedBefore + 'T00%3A00%3A00Z' if(@CreatedBefore NOT LIKE @CreatedBefore + '%Z') set @CreatedBefore=@CreatedBefore + 'Z' end set @CreatedAfter = isnull(@CreatedAfter,'') set @CreatedBefore = isnull(@CreatedBefore,'') set @sql = 'SELECT * FROM OPENQUERY([AMAZON-MWS-XML] , '' SELECT ReportRequestId FROM $ ' + @limitClase +' WITH( Src=''''https://mws.amazonservices.com/Orders/2013-09-01'''' ,Filter=''''$.RequestReportResponse.RequestReportResult.ReportRequestInfo'''' ,ElementsToTreatAsArray=''''Order'''' ,RequestData=''''Action=ListOrders[$tag$]' + @CreatedAfter + @CreatedBefore + '&MarketplaceId.Id.1='+ @MarketplaceId +'&SellerId='+ @SellerId +''''' ,RequestMethod=''''POST'''' ,NextUrlAttributeOrExpr=''''$.ListOrders[$tag$]Response.ListOrders[$tag$]Result.NextToken'''' ,NextUrlSuffix=''''&NextToken=<%nextlink_encoded%>'''' ,WaitTimeMs=20000 -- slow down to avoid throttling. 6 requests per min ,HasDifferentNextPageInfo=''''True'''' ,EnablePageTokenForBody=''''True'''' ,PagePlaceholders=''''body=|ByNextToken;filter=|ByNextToken'''' --,DataConnectionType=''''OAuth'''' --,ScopeSeparator=''''{space}'''' --,ServiceProvider=''''AmazonMWS'''' --,ClientId=''''AKIxxxxxx'''' --,ClientSecret=''''AKIxxxxxx'''' --,UseCustomApp=''''True'''' ,CacheFileLocation=''''c:\temp\mws-orders.cache'''' ,CacheEntryTtl=300 --send every 5 mins else use from cache ,IncludeParentColumns=''''False'''' ) '')' print @sql EXECUTE( @sql) |
Here is how to call this proc. Change SellerId, MarketplaceId and Date.
1 |
exec usp_MWS_ListOrders @SellerId='Axxxxxxx', @MarketplaceId ='Bxxxxxxx',@CreatedAfter='2019-01-01' |
Download Amazon MWS Report data in SQL Server (CSV / XML Format)
Now lets look at how to extract data from Custom Report API (You must need ODBC PowerPack v1.1.1 or higher). However reading data from Reports not single step process because report generation is Job style API. Which means you send report request and wait until its done. Once Report ready you have to read in CSV format or XML. Some Reports only available in CSV format. Check this post to understand how complex it can be to get data. We will make it simple for you to understand this in 3 steps. Basically calling reports requires minimum 3 API calls (see below)
- Create a new report request – Cal RequestReport API . It returns ReportRequestId (You can use it in the next step)
- Check Report Status see its done – Call GetReportRequestList API (Pass ReportRequestId got in the previous step to get data for only one Report request we care). Keep checking Report Status every few seconds until you get _DONE_ or _DONE_NO_DATA_ status in response.
- Read Report Data – Call GetReport. This API call returns CSV or XML data. So use correct Driver for this step. If CSV data is returned then we must use CSV Driver rather than XML Driver.
Method 1 – Single query approach (New Driver)
In new driver ZappySys added few new features which makes it possible to call above 3 steps process in a single query. New query syntax offers StatusCheck and Mixing Content Formats using same driver. Because Most MWS Reports are in CSV Format we have to use CSV Driver but oddly first 2 steps listed in above sections are in XML Format so we have to use XML driver. Technically we need atleast 2 steps (i.e 2 queries) but we will show you how to achieve using single query as below.
- Assuming you have followed steps to create a linked server AMAZON-MWS-CSV (see previous section)
- Run below query. Replace necessary parameters as per your need. (i.e MarketplaceId , SellerId, CreatedAfter date)
123456789101112131415161718192021222324252627282930313233343536373839404142434445--- //////////////////////////////////////////////////////////////////////////-- Change _GET_MERCHANT_LISTINGS_DATA_ to something else if you need different report type (all 3 steps) -- https://docs.developer.amazonservices.com/en_US/reports/Reports_ReportType.html-- Replace MarketplaceId in all 3 steps (i.e for USA use ATVPDKIKX0DER) --https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Endpoints.html-- Replace SellerId in all 3 steps-- Remove or Change CreatedAfter in first step (or use CreatedBefore parameter instread of CreatedAfter)--- //////////////////////////////////////////////////////////////////////////select * into tmpMWS_Report from OPENQUERY([AMAZON-MWS-CSV],'SELECT s3.* FROM $WITH(Src=''https://mws.amazonservices.com/Reports/2009-01-01'',RequestMethod=''POST'',RequestData=''Action=RequestReport&ReportType=_GET_MERCHANT_LISTINGS_DATA_&MarketplaceId=ATVPDKIKX0DER&SellerId=Axxxxxxxxxx&CreatedAfter=2017-12-31T04%3A00%3A00Z'',IncludeParentColumns=''False'',EnableRawOutputModeSingleRow=''True'',RawOutputFilterExpr=''//*[local-name()="ReportRequestId"]'',RawOutputDataRowTemplate=''{ReportRequestId:"[$1]"}'',RawOutputExtractMode=''Xml'',WaitTimeMs=5000,Meta=''[{"Name": "ReportRequestId","Type": "Int64"}]'',Alias=''s1'',Join1_alias=''s2'',Join1_Src=''https://mws.amazonservices.com/Reports/2009-01-01'',Join1_RequestMethod=''POST'',Join1_RequestData=''Action=GetReportRequestList&ReportRequestIdList.Id.1=[$s1.ReportRequestId$]&MarketplaceId=ATVPDKIKX0DER&SellerId=Axxxxxxxxxxxxx'',Join1_EnableRawOutputModeSingleRow=''True'',Join1_RawOutputFilterExpr=''//*[local-name()="ReportProcessingStatus"]||//*[local-name()="GeneratedReportId"]'',Join1_RawOutputDataRowTemplate=''{ReportProcessingStatus:"[$1]",GeneratedReportId:"[$2]"}'',Join1_RawOutputExtractMode=''Xml'',Join1_EnableStatusCheck=''True'',,Join1_StatucCheckMaxWaitSeconds=300,,Join1_StatucCheckIterationWaitSeconds=25,,Join1_StatusSuccessValue=''_DONE_'',Join1_StatusFailedValue=''_DONE_NO_DATA_|_CANCELLED_'',Join2_Alias=''s3'',Join2_Src=''https://mws.amazonservices.com/Reports/2009-01-01'',Join2_RequestMethod=''POST'',Join2_RequestData=''Action=GetReport&ReportId=[$s2.GeneratedReportId$]&MarketplaceId=ATVPDKIKX0DER&SellerId=Axxxxxxxxxxxxxx'',Join2_ColumnDelimiter=''{TAB}'',Join2_ResponseCharset=''Windows-1252'',Join2_EnableStatusCheck=''False'',Join2_EnableRawOutputModeSingleRow=''False'',Join2_WaitTimeMs=10000)')goselect * from tmpMWS_Report
Performance Tip
If you like to improve performance and dont want to use SELECT INTO approach to load into temp table as above then you can use EXEC (….) AT YourLinkedServerName as below.
Advantage of this method is your Query speed will increase because system calls API only once when you call EXEC AT. In OPENROWSET it needs to call above query twice (Once to obtain metadata and once to get data).
1 2 |
INSERT INTO tmpMWS_Report EXEC('select s3.* .................. ') AT [AMAZON-MWS-CSV] |
Method 2 – Multiple query approach (For old driver)
Now lets see how to load Amazon MWS data in SQL Server using old driver (v1.1.2 or older) which didnt support single query approach like previous section. If you are using older driver or for some reason you like to split steps into multiple procedures then use below approach.
usp_MWS_Report Stored Proc ( Generate ReportRequest, Wait until done, Read data )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
USE MyDatabase GO /* Examples: Get ReportType from here https://docs.developer.amazonservices.com/en_UK/reports/Reports_ReportType.html exec usp_MWS_Report @MarketplaceId ='ATVPDKIKX0DER', @SellerId='AZxxxxxxxx', @ReportType = '_GET_MERCHANT_LISTINGS_DATA_' exec usp_MWS_Report @MarketplaceId ='ATVPDKIKX0DER', @SellerId='AZxxxxxxxx', @ReportType = '_GET_FLAT_FILE_ORDER_REPORT_DATA_' --Do not Throw Error if no data found (return empty resultset or run custom sql) exec usp_MWS_Report @MarketplaceId ='ATVPDKIKX0DER', @SellerId='AZxxxxxxxx', @ReportType = '_GET_FLAT_FILE_ORDER_REPORT_DATA_',@ThrowErrIfNoData=0,@EmptyRowSql='select top 0 * from Orders' --Supply date range exec usp_MWS_Report @MarketplaceId ='ATVPDKIKX0DER', @SellerId='AZxxxxxxxx', @ReportType = '_GET_MERCHANT_LISTINGS_DATA_', @StartDate='2019-01-01T00:00:00Z', @EndDate='2019-01-31T00:00:00Z' --loading into table --////////////////////////////////// — Step-1 : Create Local Linked server to point to self --////////////////////////////////// USE [master] GO --change default catalog EXEC master.dbo.sp_addlinkedserver @server = N'ME', @srvproduct=N'', @provider=N'SQLNCLI11', @datasrc=N'localhost', @catalog=N'Northwind' EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'ME',@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpassword=NULL GO --////////////////////////////////// — Step-2 : Enable RPC OUT and Disable MSDTC --////////////////////////////////// EXEC sp_serveroption 'ME', 'rpc out', true; GO --Below needed to support EXEC + INSERT (dynamic query) EXEC sp_serveroption 'ME', 'remote proc transaction promotion', false; GO --test simple query select * from OPENQUERY(ME,'select 1') GO --////////////////////////////////// — Step-3 : Load data into table from MWS Report --////////////////////////////////// SELECT * INTO #amazon_mws_report FROM OPENQUERY(me,' SET NOCOUNT ON; EXEC usp_MWS_Report @Columns=''[item-name], [item-description], [listing-id]'', @MarketplaceId =''ATVPDKIKX0DER'', @SellerId=''Axxxxxxxxxxxxxxxxx'', @ReportType = ''_GET_MERCHANT_LISTINGS_DATA_'' WITH RESULT SETS ( (itmname varchar(1000),itmdesc varchar(1000),itmid varchar(1000)) ) ') select * from #amazon_mws_report */ CREATE proc [dbo].[usp_MWS_Report] @MarketplaceId varchar(100), @SellerId varchar(100), @ReportType varchar(100)='_GET_MERCHANT_LISTINGS_DATA_', @StartDate varchar(100)=null, @EndDate varchar(100)=null, @ReportId bigint=null, ---i.e. 14783134522018025 @ThrowErrIfNoData bit=1, @EmptyRowSql varchar(1000)=null, --SQL to run if no data found @Columns varchar(8000)='*' --report columns which goes in final SELECT e.g. [item-name], [item-description], [listing-id] .... as declare @retGeneratedReportId bigint set @retGeneratedReportId=@ReportId ---////// STEP 1 ///////// if(@ReportId is null) begin create table #step1(ReportRequestId bigint) insert into #step1 exec usp_MWS_RequestReport @ReportType,@MarketplaceId,@SellerId,@StartDate,@EndDate --select * from #step1 --debug declare @retReportRequestId bigint select @retReportRequestId=ReportRequestId from #step1 ---////// STEP 2 ///////// declare @status varchar(100) declare @cnt int create table #step2(ReportProcessingStatus varchar(100),GeneratedReportId bigint) --Keep looping until status is done or we waited too long while(isnull(@status,'') IN ('','_SUBMITTED_','_IN_PROGRESS_') ) begin truncate table #step2 insert into #step2 exec usp_MWS_GetReportIdAndStatus @retReportRequestId,@MarketplaceId,@SellerId select @status=ReportProcessingStatus, @retGeneratedReportId=GeneratedReportId from #step2 if(isnull(@status,'') IN ('','_SUBMITTED_','_IN_PROGRESS_') ) begin --amazon says dont check often https://docs.developer.amazonservices.com/en_UK/reports/Reports_GetReportRequestList.html Print 'Status='+ isnull(@status,'') +'. Checking after 45 sec... #' + cast(@cnt as varchar(10)) WAITFOR DELAY '00:00:45' end else print @status set @cnt=@cnt+1 --if(@cnt>50) --//throw err? end --select * from #step2 --debug end if(@retGeneratedReportId is null and @status='_DONE_NO_DATA_') begin if(@ThrowErrIfNoData=1) RAISERROR('Cannot generate report - No data found for specified criteria',16,1); else if (isnull(@EmptyRowSql,'')<>'') execute(@EmptyRowSql) end else if(@retGeneratedReportId is null) RAISERROR('Cannot generate report - Unknown error (either report got cancelled or other error occurred)',16,1); ---////// STEP 3 ///////// --If xml format of report data then use XML driver else CSV (most are Tab delimited reports in CSV format) --exec usp_MWS_GetReportDataXml @retGeneratedReportId,@MarketplaceId,@SellerId exec usp_MWS_GetReportDataCsv @retGeneratedReportId,@MarketplaceId,@SellerId,@Columns drop table #step1 drop table #step2 GO |
usp_MWS_RequestReport Stored Proc ( Step1 – Create Report Request )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
USE [MyDatabase] GO CREATE proc [dbo].[usp_MWS_RequestReport] @ReportType varchar(100), @MarketplaceId varchar(100), @SellerId varchar(100), @StartDate varchar(100)=null, @EndDate varchar(100)=null as /*Learn more : https://docs.developer.amazonservices.com/en_UK/reports/Reports_RequestReport.html */ --//Confirm ISO Date format 2019-06-01T04%3A00%3A00Z rather 2019-06-01T04:00:00Z if(isnull(@StartDate,'')<>'') begin set @StartDate='&StartDate=' + @StartDate set @StartDate=replace(@StartDate,':','%3A') if(@StartDate NOT LIKE @StartDate + 'T%') set @StartDate=@StartDate + 'T00%3A00%3A00Z' if(@StartDate NOT LIKE @StartDate + '%Z') set @StartDate=@StartDate + 'Z' --//T04%3A00%3A00Z end if(isnull(@EndDate,'')<>'') begin set @EndDate='&EndDate=' + @EndDate set @EndDate=replace(@EndDate,':','%3A') if(@EndDate NOT LIKE @EndDate + 'T%') set @EndDate=@EndDate + 'T00%3A00%3A00Z' if(@EndDate NOT LIKE @EndDate + '%Z') set @EndDate=@EndDate + 'Z' end set @StartDate = isnull(@StartDate,'') set @EndDate = isnull(@EndDate,'') declare @sql varchar(max) set @sql = 'SELECT * FROM OPENQUERY([AMAZON-MWS-XML] , '' SELECT ReportRequestId FROM $ WITH( Src=''''https://mws.amazonservices.com/Reports/2009-01-01'''',RequestMethod=''''POST'''' --,ElementsToTreatAsArray=''''Product'''' ,Filter=''''$.RequestReportResponse.RequestReportResult.ReportRequestInfo'''' ,RequestData=''''Action=RequestReport&ReportType=' + @ReportType + '&MarketplaceId='+ @MarketplaceId +'&SellerId='+ @SellerId + @StartDate + @EndDate +''''' ,CacheFileLocation=''''c:\temp\mws-cache-step-1.cache'''' ,CacheEntryTtl=300 --send every 5 mins else use from cache ,WaitTimeMs=''''300'''' ,IncludeParentColumns=''''False'''' ,Meta=''''[{"Name": "ReportRequestId","Type": "Int64"}]'''' )'')' --print @sql EXECUTE( @sql) --sleep 25 seconds after this - hope report is ready by that time else We have to loop WAITFOR DELAY '00:00:25' --lets wait 30 sec... incase we get luck and report is done? GO |
usp_MWS_GetReportIdAndStatus Stored Proc ( Step2 – Get Report Id and Report Status )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
USE MyDatabase GO CREATE proc [dbo].[usp_MWS_GetReportIdAndStatus] @ReportRequestId bigint, @MarketplaceId varchar(100), @SellerId varchar(100) as declare @sql varchar(max) set @sql = 'SELECT * FROM OPENQUERY([AMAZON-MWS-XML] , ''SELECT * FROM $ WITH( Src=''''https://mws.amazonservices.com/Reports/2009-01-01'''',RequestMethod=''''POST'''' ,ElementsToTreatAsArray=''''ReportRequestInfo'''' ,Filter=''''$.GetReportRequestListResponse.GetReportRequestListResult.ReportRequestInfo'''' ,RequestData=''''Action=GetReportRequestList&ReportRequestIdList.Id.1=' + cast(@ReportRequestId as varchar(20)) + '&MarketplaceId='+ @MarketplaceId +'&SellerId='+ @SellerId +''''' ,WaitTimeMs=''''300'''' ,IncludeParentColumns=''''False'''' --,CacheFileLocation=''''c:\temp\mws-cache-step-2.cache'''' --,CacheEntryTtl=10 --do not use from cache too old.. but cache still prevents too many requests ,Meta=''''[{"Name": "ReportProcessingStatus","Type": "String", Length: 100},{"Name": "GeneratedReportId","Type": "Int64"}]'''' )'')' --print @sql EXECUTE( @sql) GO |
usp_MWS_GetReportDataCsv Stored Proc (Step3 – Get Report Data in CSV format )
Last step in report generation is download the report data in CSV format.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
USE MyDatabase GO CREATE proc [dbo].[usp_MWS_GetReportDataCsv] @ReportId bigint, @MarketplaceId varchar(100), @SellerId varchar(100), @Columns varchar(8000)='*' as declare @sql varchar(max) set @sql = 'SELECT '+ @Columns +' FROM OPENQUERY([AMAZON-MWS-CSV], ''SELECT * FROM $ WITH( Src=''''https://mws.amazonservices.com/Reports/2009-01-01'''',RequestMethod=''''POST'''' ,RequestData=''''Action=GetReport&ReportId=' + cast(@ReportId as varchar(20)) + '&MarketplaceId='+ @MarketplaceId +'&SellerId='+ @SellerId +''''' ,WaitTimeMs=''''300'''' ,ColumnDelimiter=''''{TAB}'''' ,ResponseCharset=''''Windows-1252'''' ,CacheFileLocation=''''c:\temp\mws-cache-step-3.cache'''' ,CacheEntryTtl=300 --once report is generated lets try to read from cache )'' )' print @sql EXECUTE( @sql) GO |
Example – Import data from Amazon MWS into SQL Server Table
Finally when we have all stored procs created we can load into target table as below. In our previous article we saw how to use SELECT INTO along with OPENQUERY to load data into new temp table or insert into some existing table. However when you want to load Stored Proc output into table its not straight forward specially when we calling dynamic SQL.
Three tricks worth mentioning here which makes it possible to load data from stored proc into temp table dynamically.
- Create a linked server to Self so we can use OPENQUERY against to call stored proc so its easy to use SELECT INTO.
- Use WITH RESULT SETS to describe metadata of output. This is needed because we are using dynamic SQL inside proc and WITH RESULT SETS describes the metadata.
- Use of SET NO COUNT ON to avoid error like below
12"SOMESERVERNAME" indicates that either the object has no columnsor the current user does not have permissions on that object - If you dont do above tricks then you may see errors like this (INSERT is not allowed when we use DYNAMIC SQL inside nested Stored Procs)
To load output into table you must know column names from the output. If you dont know you can try to run stored proc without @Columns like below.
1 |
EXEC usp_MWS_Report @MarketplaceId =''ATVPDKIKX0DER'', @SellerId=''Axxxxxxxxxxxxx'', @ReportType = ''_GET_MERCHANT_LISTINGS_DATA_'' |
Once we know columns from report, you can run following script to insert into table.
Full Script – Load MWS Report Output into Table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
--////////////////////////////////// — Step-1 : Create Local Linked server to point to self --////////////////////////////////// USE [master] GO --change default catalog EXEC master.dbo.sp_addlinkedserver @server = N'ME', @srvproduct=N'', @provider=N'SQLNCLI11', @datasrc=N'localhost', @catalog=N'Northwind' EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'ME',@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpassword=NULL GO --////////////////////////////////// — Step-2 : Enable RPC OUT and Disable MSDTC --////////////////////////////////// EXEC sp_serveroption 'ME', 'rpc out', true; GO --Below needed to support EXEC + INSERT (dynamic query) EXEC sp_serveroption 'ME', 'remote proc transaction promotion', false; GO --test simple query select * from OPENQUERY(ME,'select 1') GO --////////////////////////////////// — Step-3 : Load data into temp table from Amazon MWS Report --////////////////////////////////// SELECT * INTO #amazon_mws_report FROM OPENQUERY(me,' SET NOCOUNT ON; EXEC usp_MWS_Report @Columns=''[item-name], [item-description], [listing-id]'', @MarketplaceId =''ATVPDKIKX0DER'', @SellerId=''Axxxxxxxxxxxxx'', @ReportType = ''_GET_MERCHANT_LISTINGS_DATA_'' WITH RESULT SETS ( (itmname varchar(1000),itmdesc varchar(1000),itmid varchar(1000)) ) ') select * from #amazon_mws_report |
Conclusion
In this article, we saw how to load Amazon MWS Data into SQL Server. We used simple SQL queries with ZappySys XML / CSV Driver to pull data from Amazon MWS API. ZappySys ODBC PowerPack makes it super easy to consume data from virtually any API (JSON / XML or CSV Web Services), no coding required. Download here to get started with ZappySys ODBC drivers.