OpenJson or Table-Valued Parameters as Stored procedure parameters.

Which one is the better option?

SP Sarkar
5 min readDec 14, 2023

In the dynamic world of database management, SQL Server offers various tools to handle data efficiently. When it comes to handling JSON data, developers often find themselves at a crossroads between two popular options: OpenJson and Table-Valued Parameters (TVPs). In this guide, we’ll break down the pros and cons of each, helping you make an informed decision based on your specific needs.

OpenJson

OpenJson is a table-valued function available in Microsoft SQL Server that allows you to parse and extract data from JSON documents within your SQL queries. It essentially transforms the nested structure of JSON data into a relational table format with rows and columns, making it easier to query and integrate with your existing database schema.

Here’s an example of using OpenJson to parse a JSON string containing customer information and extract specific data into a relational table:

[
{
"CustomerID": 1,
"Name": "John Smith",
"Address": {
"Street": "1 Main St",
"City": "New York",
"State": "NY",
"ZipCode": "10001"
},
"Orders": [
{
"OrderID": 123,
"OrderDate": "2023-12-14",
"Total": 100.00
},
{
"OrderID": 456,
"OrderDate": "2023-12-10",
"Total": 50.00
}
]
},
{
"CustomerID": 2,
"Name": "Jane Doe",
"Address": {
"Street": "10 Elm St",
"City": "Los Angeles",
"State": "CA",
"ZipCode": "90001"
},
"Orders": [
{
"OrderID": 789,
"OrderDate": "2023-12-08",
"Total": 200.00
}
]
}
]
DECLARE @json NVARCHAR(MAX) = N'YOUR JSON STRING HERE';

SELECT
c.CustomerID,
c.Name,
a.Street,
a.City,
a.State,
a.ZipCode,
o.OrderID,
o.OrderDate,
o.Total
FROM OPENJSON(@json, '$.') AS c
CROSS APPLY OPENJSON(c.Address, '$.') AS a
LEFT JOIN OPENJSON(c.Orders, '$.') AS o ON c.CustomerID = o.CustomerID;
  1. We declare a variable @json to hold the JSON string.
  2. The main OPENJSON function parses the entire JSON array and returns each customer object as a separate row.
  3. We use a CROSS APPLY clause with another OPENJSON call to further parse the nested Address object for each customer and extract the desired information.
  4. We use a LEFT JOIN with yet another OPENJSON call to parse the nested Orders array for each customer and extract the desired order information. This LEFT JOIN ensures we capture all customers, even if they have no orders.
  5. Finally, we select the desired columns from each source, including customer data, address details, and order details.

Key features of OpenJson:

  • Flexibility: It can handle various JSON structures, including objects, arrays, and nested data.
  • Ease of use: You only need to provide the JSON string as input, making it simple to integrate into your existing queries.
  • Efficient for small data: For smaller JSON datasets, OpenJson can be quite efficient in terms of performance.
  • Data manipulation: While not as extensive as other methods, it allows some filtering and transformation of data during parsing.

Limitations of OpenJson:

  • Performance: For large or complex JSON data, OpenJson can become slower than other options like Table-valued Parameters (TVPs).
  • Limited data manipulation: Compared to TVPs or other methods, it offers less flexibility for modifying or filtering data before processing.
  • Memory issues: Handling large datasets can lead to memory limitations depending on your server configuration.

Here are some common scenarios where OpenJson might be useful:

  • Extracting specific data points from JSON logs or API responses.
  • Importing simple JSON data into your relational database.
  • Joining JSON data with existing tables based on shared fields.
  • Analyzing and filtering JSON data within your SQL queries.

Overall, OpenJson is a powerful tool for working with JSON data in SQL Server, but it’s important to consider its limitations and compare it to other options like TVPs for optimal performance and flexibility depending on your specific needs.

Table-Valued Parameters

In SQL Server, Table-valued Parameters (TVPs) are a powerful way to send large, complex datasets to stored procedures or functions as a single parameter. They essentially act as virtual tables that can hold multiple rows and columns, similar to a regular table but existing only within the context of the procedure or function call.

Here’s an example of using Table-valued Parameters (TVPs) to send a list of customer IDs to a stored procedure and update their addresses in bulk:

1. Create the User-defined Table Type (UDT):

First, we need to create a UDT that defines the schema of the data you want to pass through the TVP. This UDT specifies the names and data types of the columns.

CREATE TYPE AddressInfo AS TABLE (
CustomerID INT PRIMARY KEY,
Street NVARCHAR(100) NOT NULL,
City NVARCHAR(50) NOT NULL,
State NVARCHAR(2) NOT NULL,
ZipCode NVARCHAR(10) NOT NULL
);
GO

2. Define the Stored Procedure:

In the stored procedure or function, we need to declare a parameter of the type table and reference the UDT we just created. This parameter becomes the TVP.

CREATE PROCEDURE UpdateCustomerAddresses (@addresses AddressInfo READONLY)
AS
BEGIN
UPDATE Customers
SET Street = a.Street, City = a.City, State = a.State, ZipCode = a.ZipCode
FROM Customers c
INNER JOIN @addresses a ON c.CustomerID = a.CustomerID;
END
GO

3. Populate the TVP and call the Stored Procedure:

Before calling the procedure or function, we can populate the TVP with data using various methods, like INSERT statements or loading data from external sources.

DECLARE @customerAddresses AddressInfo;

INSERT INTO @customerAddresses (CustomerID, Street, City, State, ZipCode)
VALUES (1, '123 Main St', 'New York', 'NY', '10001'),
(2, '456 Elm St', 'Los Angeles', 'CA', '90001'),
(3, '789 Oak St', 'Chicago', 'IL', '60601');

4. Execution

Inside the procedure or function, we can access the TVP data like any other table. We can use it in joins, filters, and other operations to process the data efficiently.

EXEC UpdateCustomerAddresses @customerAddresses;P

Process Summary

  1. We create a UDT named AddressInfo with the desired customer address information columns.
  2. We define a stored procedure named UpdateCustomerAddresses that takes the @addresses TVP as a parameter of type AddressInfo.
  3. Inside the stored procedure, we use an UPDATE statement with an INNER JOIN to update the corresponding customer addresses in the Customers table based on the matching CustomerID values.
  4. We populate the @customerAddresses TVP with three sample customer records.
  5. Finally, we call the stored procedure and pass the @customerAddresses TVP as an argument.

Benefits of using TVPs:

  • Improved performance and efficiency.
  • Cleaner and more maintainable code.
  • Enhanced flexibility for handling complex data structures.
  • Increased reusability of data types and procedures.

However, TVPs also have some limitations:

  • Setup required: Creating the UDT and understanding the syntax can have a learning curve.
  • Overhead: For very small datasets, the overhead of creating and populating a TVP might outweigh its benefits.
  • Less flexibility than OpenJson: While offering data manipulation within the TVP, OpenJson might be more suitable for specific parsing and transformation needs.

Overall, TVPs are a valuable tool for passing and processing large, complex datasets in SQL Server. They offer performance improvements, code reusability, and improved data organization compared to other methods like individual parameters or temporary tables. Consider your specific needs and data size when choosing between TVPs and other options for optimal results.

Conclusion:

Ultimately, the choice between OpenJson and TVPs in SQL Server depends on your specific needs. If you prioritize flexibility and simplicity for smaller datasets, OpenJson might be the way to go. On the other hand, if efficiency, data manipulation, and scalability are paramount, TVPs could be your go-to solution. Remember, the best choice is the one aligned with your unique requirements and priorities.

In your SQL Server journey, understanding these tools’ strengths and weaknesses will empower you to make informed decisions, optimizing performance and ensuring a seamless data handling experience. Happy coding!

I write about step-by-step coding tutorials on fullstack Development and Microservices architecture on LinkedIn, and Medium. Here is My Linkedin profile.

--

--

SP Sarkar

Software Engineer. Startups Enthusiastic. I mostly write about Coding and Marketing.