Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Qual è il modo ottimale per ottenere record dal database nello scenario in cui devi passare elenchi in cui ognuno di essi ha più di 2000 parametri?

I parametri con valori di tabella sono la strada da percorrere se questo è davvero il modo in cui devi affrontare questo argomento.

  • In primo luogo, passa a una stored procedure poiché stai utilizzando SQL 2008 o versioni successive.
  • Secondo, leggi il using dichiarazione per lo smaltimento degli elementi di yoursql.

Psuedo livello dati:

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 la tvp:

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

)

Crea il processo memorizzato:

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 è necessario aggiungere un secondo set di parametri numerici, è possibile passare più parametri di tipo diverso al database. In passato, abbiamo creato diversi tipi generici per supportare elenchi di tipi di dati variabili invece di dover gestire molti tipi di tabelle.

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

Cose importanti da ricordare:

  • Il tipo di parametro per un tvp deve essere SqlDbType.Structured
  • Il TypeName per il parametro deve corrispondere al nome del tipo di parametro del valore della tabella.
  • Il parametro Table Value Parameter nella procedura memorizzata deve essere dichiarato come READONLY