
こんにちは。CData Software Japan の杉本です。
CData API Server ではオンプレミスにあるデータベースのテーブルを簡単にAPI として公開することが可能です。その際に複数のテーブルをまとめて取得したい場合に利用可能な方法についてご説明いたします。
前提
今回は説明にあたり、SQL Server 側に以下のようなテーブルとサンプルデータを複数用意します。
これらのテーブルを一度に取得する場合、SQL であればJOIN 等を利用して取得が可能です。
-- ============================================
-- テーブル作成
-- ============================================
-- 顧客テーブル
CREATE TABLE Customers (
CustomerID INT PRIMARY KEY IDENTITY(1,1),
CustomerName NVARCHAR(100) NOT NULL,
Email NVARCHAR(100),
Country NVARCHAR(50),
CreatedDate DATETIME DEFAULT GETDATE()
);
-- 商品テーブル
CREATE TABLE Products (
ProductID INT PRIMARY KEY IDENTITY(1,1),
ProductName NVARCHAR(100) NOT NULL,
Category NVARCHAR(50),
UnitPrice DECIMAL(10, 2) NOT NULL,
StockQuantity INT DEFAULT 0,
CreatedDate DATETIME DEFAULT GETDATE()
);
-- 注文テーブル
CREATE TABLE Orders (
OrderID INT PRIMARY KEY IDENTITY(1,1),
CustomerID INT NOT NULL,
OrderDate DATETIME DEFAULT GETDATE(),
TotalAmount DECIMAL(10, 2),
Status NVARCHAR(20) DEFAULT 'Pending',
ShippingAddress NVARCHAR(200),
CONSTRAINT FK_Orders_Customers FOREIGN KEY (CustomerID)
REFERENCES Customers(CustomerID)
);
-- 注文明細テーブル
CREATE TABLE OrderDetails (
OrderDetailID INT PRIMARY KEY IDENTITY(1,1),
OrderID INT NOT NULL,
ProductID INT NOT NULL,
Quantity INT NOT NULL,
UnitPrice DECIMAL(10, 2) NOT NULL,
Subtotal AS (Quantity * UnitPrice) PERSISTED,
CONSTRAINT FK_OrderDetails_Orders FOREIGN KEY (OrderID)
REFERENCES Orders(OrderID),
CONSTRAINT FK_OrderDetails_Products FOREIGN KEY (ProductID)
REFERENCES Products(ProductID)
);
GO
-- ============================================
-- テストデータ投入
-- ============================================
-- 顧客データ
INSERT INTO Customers (CustomerName, Email, Country) VALUES
('CData太郎', '[email protected]', 'Japan'),
('CData花子', '[email protected]', 'Japan'),
('CData一郎', '[email protected]', 'Japan'),
('CData美咲', '[email protected]', 'Japan'),
('CData健太', '[email protected]', 'Japan');
-- 商品データ
INSERT INTO Products (ProductName, Category, UnitPrice, StockQuantity) VALUES
('ノートパソコン', 'Electronics', 89800.00, 50),
('ワイヤレスマウス', 'Electronics', 2980.00, 150),
('USB-Cケーブル', 'Accessories', 1280.00, 300),
('モニター 27インチ', 'Electronics', 34800.00, 30),
('キーボード', 'Electronics', 8900.00, 80),
('Webカメラ', 'Electronics', 5800.00, 60),
('ヘッドセット', 'Electronics', 7200.00, 100),
('外付けSSD 1TB', 'Storage', 12800.00, 40),
('スマートフォンスタンド', 'Accessories', 1500.00, 200),
('モバイルバッテリー', 'Accessories', 3800.00, 120);
-- 注文データ
INSERT INTO Orders (CustomerID, OrderDate, Status, ShippingAddress) VALUES
(1, '2024-10-01', 'Completed', 'テスト住所'),
(1, '2024-10-15', 'Shipped', 'テスト住所'),
(2, '2024-10-05', 'Completed', 'テスト住所'),
(3, '2024-10-10', 'Processing', 'テスト住所'),
(4, '2024-10-20', 'Pending', 'テスト住所'),
(5, '2024-10-25', 'Shipped', 'テスト住所'),
(2, '2024-10-28', 'Processing', 'テスト住所');
-- 注文明細データ
-- 注文1(CData太郎の1回目)
INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice) VALUES
(1, 1, 1, 89800.00),
(1, 2, 2, 2980.00),
(1, 3, 3, 1280.00);
-- 注文2(CData太郎の2回目)
INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice) VALUES
(2, 4, 1, 34800.00),
(2, 5, 1, 8900.00);
-- 注文3(CData花子の1回目)
INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice) VALUES
(3, 6, 1, 5800.00),
(3, 7, 1, 7200.00),
(3, 9, 2, 1500.00);
-- 注文4(CData一郎)
INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice) VALUES
(4, 1, 1, 89800.00),
(4, 8, 1, 12800.00);
-- 注文5(CData美咲)
INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice) VALUES
(5, 2, 3, 2980.00),
(5, 3, 5, 1280.00),
(5, 10, 2, 3800.00);
-- 注文6(CData健太)
INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice) VALUES
(6, 4, 2, 34800.00),
(6, 5, 2, 8900.00);
-- 注文7(CData花子の2回目)
INSERT INTO OrderDetails (OrderID, ProductID, Quantity, UnitPrice) VALUES
(7, 1, 1, 89800.00),
(7, 6, 1, 5800.00);
-- 注文の合計金額を更新
UPDATE Orders
SET TotalAmount = (
SELECT SUM(Subtotal)
FROM OrderDetails
WHERE OrderDetails.OrderID = Orders.OrderID
);
次にCData API Server にログインして、上記で追加したテーブルが存在するSQL Server への接続設定を作成します。

接続を追加 > SQL Server を選択します。

接続に必要な情報を指定します。

次にSQL Server のテーブルをAPI として公開します。

テーブルを追加より、まずは接続を選択します。

次にAPI として公開するテーブルを選択します。

追加されると以下のようにAPI エンドポイントとしてテーブルが公開されます。
デフォルトではエンドポイントは<データベース名>_<スキーマ名>_<テーブル名>となります。

テーブル名>スキーマ名>データベース名>
この状態でまずはPostman から個別のテーブルにアクセス出来ることを確認します。

これで前提の準備が完了です。
OData の$expand キーワードを利用する
CData API Server はOData の$expand キーワードをサポートしています。これにより、単一リクエストでレコードおよび関連エンティティからのデータを取得することができます。
$expand キーワードを利用する場合は、CData API Server テーブルでエンティティ間のリレーションシップを定義する必要があります。またリレーションシップの書式はリレーションシップの種類によって記法が異なります。
一対多のリレーションシップ
Customers テーブルに対する Orders テーブルのリレーションシップを定義する場合、まずは追加したCustomers テーブルの定義を編集します。

次にリレーションシップを定義するカラムを選択します。今回はCustomerID の項目で紐づけを行うため、CustomerID を選択します。

CustomerID のリレーションシップを次のように定義します。
*Orders(APIServerTest_dbo_Orders.CustomerID)

形式としては以下の形式となります。
relationshipName(TableName.ColumnName)
ここでの注意点としては一対多のリレーションシップの場合は、カーディナリティを示すアステリスク (*) をrelationshipName の先頭に付与する必要があります。アスタリスクをつけなくともエラーにはなりませんが、取得されるOrders テーブルのデータは各レコード1件のみとなります。
上記の設定が完了したら、Postman からAPI にアクセスしてCustomers と Orders の関連データが一度に取得出来ることを確認します。
なおリクエストを行う際は$expand キーワードを利用して、作成したリレーションシップ名を指定します。
例:http://MyServer:MyPort/api.rsc/APIServerTest_dbo_Customers?$expand=Orders

多対一のリレーションシップ
次は反対にOrders テーブルにCustomers テーブルのリレーションシップを定義する方法を説明します。
Orders テーブルのAPI 設定から、CustomerID に以下のようなリレーションシップを定義します。
CustomersOrder(APIServerTest_dbo_Customers.CustomerID)

今回は多対一のリレーションシップとなるため、アステリスクは不要です。
そしてPostman からAPI にアクセスして、関連するCustomers テーブルのデータが取得されていることを確認します。
例:http://MyServer:MyPort/api.rsc/APIServerTest_dbo_Orders?$expand=CustomersOrder

その他
複数のリレーションシップを一度に指定することも可能です。
例:http://MyServer:MyPort/api.rsc/APIServerTest_dbo_Orders?$expand=CustomersOrder,OrderDetails

また$expand キーワードと合わせて、$select キーワードや$filter キーワードを指定することも可能です。
例:http://MyServer:MyPort/api.rsc/APIServerTest_dbo_Orders?$expand=CustomersOrder($select=CustomerName)

例:http://MyServer:MyPort/api.rsc/APIServerTest_dbo_Customers?$expand=Orders($filter= Status eq 'Completed')

また$expand キーワードを階層的に利用することは現在サポートされていませんので、ご注意ください。
例:http://MyServer:MyPort/api.rsc/APIServerTest_dbo_Customers?$expand=Orders($expand=OrderDetails)
データソース側でViewを用意する
$expand キーワードを利用する以外の方法としては、データベース側に事前に各テーブルをJOIN したView を作成して、View をAPI として公開する方法があります。
まずは事前にSQL Server 側に以下のようなView を準備します。
CREATE VIEW vw_CustomersWithOrders AS
SELECT
-- 顧客情報(プレフィックス: c_)
c.CustomerID AS c_CustomerID,
c.CustomerName AS c_CustomerName,
c.Email AS c_Email,
c.Country AS c_Country,
c.CreatedDate AS c_CreatedDate,
-- 注文情報(プレフィックス: o_)
o.OrderID AS o_OrderID,
o.OrderDate AS o_OrderDate,
o.TotalAmount AS o_TotalAmount,
o.Status AS o_Status,
o.ShippingAddress AS o_ShippingAddress
FROM
Customers c
LEFT JOIN Orders o ON c.CustomerID = o.CustomerID;
GO
CREATE VIEW vw_OrdersExpanded AS
SELECT
-- 注文情報(プレフィックス: o_)
o.OrderID AS o_OrderID,
o.OrderDate AS o_OrderDate,
o.TotalAmount AS o_TotalAmount,
o.Status AS o_Status,
o.ShippingAddress AS o_ShippingAddress,
-- 顧客情報(プレフィックス: c_)
c.CustomerID AS c_CustomerID,
c.CustomerName AS c_CustomerName,
c.Email AS c_Email,
c.Country AS c_Country,
-- 注文明細情報(プレフィックス: od_)
od.OrderDetailID AS od_OrderDetailID,
od.ProductID AS od_ProductID,
od.Quantity AS od_Quantity,
od.UnitPrice AS od_UnitPrice,
od.Subtotal AS od_Subtotal
FROM
Orders o
INNER JOIN Customers c ON o.CustomerID = c.CustomerID
LEFT JOIN OrderDetails od ON o.OrderID = od.OrderID;
GO
CREATE VIEW vw_CustomersFullExpand AS
SELECT
-- 顧客情報(プレフィックス: c_)
c.CustomerID AS c_CustomerID,
c.CustomerName AS c_CustomerName,
c.Email AS c_Email,
c.Country AS c_Country,
c.CreatedDate AS c_CreatedDate,
-- 注文情報(プレフィックス: o_)
o.OrderID AS o_OrderID,
o.OrderDate AS o_OrderDate,
o.TotalAmount AS o_TotalAmount,
o.Status AS o_Status,
o.ShippingAddress AS o_ShippingAddress,
-- 注文明細情報(プレフィックス: od_)
od.OrderDetailID AS od_OrderDetailID,
od.Quantity AS od_Quantity,
od.UnitPrice AS od_UnitPrice,
od.Subtotal AS od_Subtotal,
-- 商品情報(プレフィックス: p_)
p.ProductID AS p_ProductID,
p.ProductName AS p_ProductName,
p.Category AS p_Category,
p.UnitPrice AS p_ProductUnitPrice,
p.StockQuantity AS p_StockQuantity
FROM
Customers c
LEFT JOIN Orders o ON c.CustomerID = o.CustomerID
LEFT JOIN OrderDetails od ON o.OrderID = od.OrderID
LEFT JOIN Products p ON od.ProductID = p.ProductID;
GO
そしてCData API Server で作成したView をAPI として公開します。

それでは公開したView をPostman からAPI にアクセスしてみましょう。
vw_CustomersWithOrders は一対多の例で説明した時と同様のデータが取得出来ることが確認出来ます。

View を利用したアプローチのメリットは、データがフラットな構造で取得されるため、受け取ったあとにクライアント側の特別な処理が不要になることです。
またvw_CustomersFullExpand では$expand キーワードを利用した場合では難しかった階層的なデータ取得を行うことも可能です。

おわりに
CData API Server ではオンプレミスにあるデータベースを簡単にAPI として公開することが可能です。ただし実務では複数のテーブルを一度に取得したいことも多いかと思います。そのような場合は本記事を参考に設定をお試しいただければと思います。
この記事では CData API Server 2025 - 25.2.9349.0 を利用しています。