sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cuál es la forma óptima de obtener registros de la base de datos en el escenario en el que tiene que pasar listas que cada una de ellas tiene más de 2000 parámetros?

Los parámetros con valores de tabla son el camino a seguir si esta es realmente la forma en que necesita abordar este tema.

  • Primero, cambie a un procedimiento almacenado ya que está utilizando SQL 2008 o posterior.
  • Segundo, lea sobre el using declaración para deshacerse de los elementos de yoursql.

Capa de pseudodatos:

public List<SalesList> ExecuteSales(List<string> items, int storeID, int W1, int W2, int vendorID, int retailerID)
{
    var sales = new List<SalesList>();
    var table = new DataTable();
    table.Columns.Add("ItemNumber");
    foreach (var item in items)
    {
        table.Rows.Add(item);
    }
    using (var connection = new SqlConnection("ConnectionString"))
    {
        connection.Open();
        using (var command = connection.CreateCommand())
        {
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = "cp_ExecuteSales";
            command.Parameters.AddWithValue("@RetailerID", retailerID);
            command.Parameters.AddWithValue("@VendorID", vendorID);
            command.Parameters.AddWithValue("@StoreID", storeID);
            var tvp = new SqlParameter("@ItemIds", SqlDbType.Structured)
            {
                 TypeName = "tvpItems",
                 Value = table
            };
            command.Parameters.Add(tvp);
            using (var reader = command.ExecuteReader())
            {
                //DoWork
            }
        }
    }
    return sales;
}

Crea el tvp:

CREATE TYPE [dbo].[tvpItems] AS TABLE(
[ItemNumber] [int] NULL

)

Crea el proceso almacenado:

CREATE PROCEDURE cp_ExecuteSales
     @RetailerID VARCHAR(50),
     @VendorID VARCHAR(50),
     @StoreID VARCHAR(50),
     @ItemIds tvpItems READONLY
AS
  SELECT  I.ITEM_NBR
          ,I.ITEM_DESC1
          ,I.ITEM_DESC2
          ,I.VENDOR_STK_NBR
          ,SUM(SA.POS_QTY) AS POS_QTY
          ,SUM(SA.POS_SALES) AS POS_SALES
  FROM  SALES_FTBL SA
        INNER JOIN ITEM_TBL I ON SA.RETAILER_ID = I.RETAILER_ID 
            AND SA.ITEM_NBR = I.ITEM_NBR
        INNER JOIN @ItemIds ID ON SA.ITEM_NBR = ID.ItemNumber
  WHERE SA.RETAILER_ID=I.RETAILER_ID
        AND SA.RETAILER_ID = @RetailerID
        AND SA.VENDOR_NBR  = @VendorID
        AND SA.STORE_NBR  = @StoreID
        AND SA.ITEM_NBR=I.ITEM_NBR

Si necesita agregar un segundo conjunto de parámetros numéricos, puede pasar múltiples parámetros de diferentes tipos a la base de datos. En el pasado, creamos varios tipos genéricos para admitir una lista variable de tipos de datos en lugar de tener que administrar muchos tipos de tablas.

CREATE TYPE [dbo].[IntList] AS TABLE(
    [Value] [Int] NULL
)

Cosas importantes para recordar:

  • El tipo de parámetro para un tvp debe ser SqlDbType.Structured
  • El TypeName para el parámetro debe coincidir con el nombre del tipo de parámetro de valor de tabla.
  • El parámetro Parámetro de valor de tabla en el procedimiento almacenado debe declararse como READONLY