Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Was ist der optimale Weg, um Datensätze aus der Datenbank zu erhalten, wenn Sie Listen übergeben müssen, die jeweils mehr als 2000 Parameter enthalten?

Tabellenwertparameter sind der richtige Weg, wenn Sie dieses Thema tatsächlich so angehen müssen.

  • Wechseln Sie zunächst zu einer gespeicherten Prozedur, da Sie SQL 2008 oder höher verwenden.
  • Sehen Sie sich als Zweites die using an Anweisung zur Entsorgung Ihrer SQL-Elemente.

Pseudodatenschicht:

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;
}

Erstellen Sie den tvp:

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

)

Erstellen Sie die gespeicherte Prozedur:

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

Wenn Sie einen zweiten Satz von Zahlenparametern hinzufügen müssen, können Sie mehrere Parameter unterschiedlichen Typs an die Datenbank übergeben. In der Vergangenheit haben wir mehrere generische Typen erstellt, um eine unterschiedliche Liste von Datentypen zu unterstützen, anstatt viele Tabellentypen verwalten zu müssen.

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

Wichtige Dinge, die Sie sich merken sollten:

  • Der Parametertyp für einen tvp muss SqlDbType.Structured sein
  • Der TypeName für den Parameter muss mit dem Namen des Tabellenwert-Parametertyps übereinstimmen.
  • Der Tabellenwert-Parameterparameter in der gespeicherten Prozedur muss als READONLY deklariert werden