Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Qual é a melhor maneira de obter registros do banco de dados no cenário que você tem que passar listas que cada uma delas tem mais de 2000 parâmetros?


Parâmetros com valor de tabela é o caminho a percorrer se esta for realmente a maneira que você precisa abordar este tópico.
  • Primeiro, mude para um procedimento armazenado, pois você está usando o SQL 2008 ou mais recente.
  • Segundo, leia sobre o using instrução para descartar itens yoursql.

Camada de dados pseudo:
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;
}

Crie o tvp:
CREATE TYPE [dbo].[tvpItems] AS TABLE(
[ItemNumber] [int] NULL

)

Crie o proc armazenado:
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

Se você precisar adicionar um segundo conjunto de parâmetros numéricos, poderá passar vários parâmetros de diferentes tipos para o banco de dados. No passado, criamos vários tipos genéricos para oferecer suporte a várias listas de tipos de dados, em vez de ter que gerenciar muitos tipos de tabela.
CREATE TYPE [dbo].[IntList] AS TABLE(
    [Value] [Int] NULL
)

Coisas importantes para lembrar:
  • O tipo de parâmetro para um tvp deve ser SqlDbType.Structured
  • O TypeName para o parâmetro deve corresponder ao nome do tipo de parâmetro do valor da tabela.
  • O parâmetro Table Value Parameter no procedimento armazenado deve ser declarado como READONLY