• subscribe
November 24, 2008 12:00 AM

Handling Arrays

Using arrays as input for stored procedures
SQL Server Pro
InstantDoc ID #100453
Downloads
100453.zip

Executive Summary: One way to use arrays as input for stored procedures in Microsoft SQL Server is to employ dynamic SQL.

Stored procedures don’t support arrays as inputs, but there’s a common need to develop procedures that accept an unknown number of input parameters. For example, suppose you need to create a procedure in the Northwind database that accepts an unknown number of order IDs as input and returns information from the Orders table about the requested orders. One of the most obvious solutions is to use dynamic SQL. This option is available in SQL Server 2008, 2005, and 2000.

Implementing the Solution
To use the dynamic SQL solution, run the code in Listing 1 to create the stored procedure usp_getorders. The implementation of the procedure is very simple. The procedure accepts a character string parameter called @arr that holds a comma-separated list of order IDs as input. The procedure constructs a character string with a query against the Orders table in a variable called @sql. In the query’s filter the code concatenates the contents of @arr in the parentheses of the IN predicate. Finally, the code uses the sp_executesql procedure to dynamically execute the code residing in the @sql variable.

I restricted the input parameter @arr to 2,000 characters. If you need to support longer strings, SQL Server 2000 lets you go up to 4,000 characters with the NVARCHAR data type and 8,000 characters with VARCHAR (which will require you to use EXEC instead of sp_executesql). In SQL Server 2005, you can use NVARCHAR(MAX) or VARCHAR(MAX) and go up to the maximum supported large object size (2GB).

Run the following code to test the procedure with two different sets of order IDs:

EXEC dbo.usp_getorders N'10248,10250,10249';
EXEC dbo.usp_getorders
  N'10260,10270,10265,10290';

For each invocation, the procedure constructs a query string in which the comma-separated order IDs appear as constants, then executes it. The query returns information from the Orders table about the requested orders. For example, the first invocation of the procedure returns the output in Table 1.

Limitations
Unfortunately, the dynamic SQL solution has serious disadvantages. These drawbacks include security, performance, and limited control over the order of rows in the output.

Security. The procedure uses dynamic SQL without validating the input, which completely exposes the procedure to SQL injection. To see how easy it is to inject code here, run the following command:

EXEC dbo.usp_getorders N'0); RAISERROR( 'This
  could have been much worse than a RAISERROR
  statement.', 16, 1); --';

The dynamic batch that is constructed by the stored procedure is:

SELECT OrderID, OrderDate, CustomerID, EmployeeID
FROM dbo.Orders
WHERE OrderID IN(0); RAISERROR( 'This could have
  been much worse than a RAISERROR statement.',
  16, 1); --);

In this example I injected a RAISERROR statement to the code for demonstration purposes, but a real injection would likely be much worse. This call to the stored procedure produces an empty set as output because I specified only one order ID that doesn’t exist (order ID 0), followed by the output of the injected RAISERROR statement.

You can try to prevent the injection by inspecting the input. In our case the input should have only digits and commas, so input validation is simple. Add the following code at the beginning of the stored procedure to check whether the input contains any character other than a digit or a comma, and if it does, raise an error and return from the procedure without executing the dynamic batch:

IF @sql LIKE N'%[^0-
9,]%'
BEGIN
  RAISERROR('Input
may contain SQL
injection. Procedure
aborted.', 16, 1);
  RETURN;
END

Run Listing 2 to create the revised procedure.

Continue to page 2



ARTICLE TOOLS

Comments
  • ELISABETH
    3 years ago
    Jan 26, 2009

    What about using XML? It's a very clean way of handling array-type data in SQL Server. I've posted a blog article about using XML for this purpose on my company web site at http://techknowsolve.com/blog/?p=13.

    Mary Delamater
    TechKnowSolve
    Portland, Oregon
    http://www.techknowsolve.com

You must log on before posting a comment.

Are you a new visitor? Register Here