sql >> Databasteknik >  >> RDS >> Sqlserver

Hur man skickar en array till en lagrad SQL Server-procedur

SQL Server 2008 (eller nyare)

Skapa först följande två objekt i din databas:

CREATE TYPE dbo.IDList
AS TABLE
(
  ID INT
);
GO

CREATE PROCEDURE dbo.DoSomethingWithEmployees
  @List AS dbo.IDList READONLY
AS
BEGIN
  SET NOCOUNT ON;

  SELECT ID FROM @List; 
END
GO

Nu i din C#-kod:

// Obtain your list of ids to send, this is just an example call to a helper utility function
int[] employeeIds = GetEmployeeIds();

DataTable tvp = new DataTable();
tvp.Columns.Add(new DataColumn("ID", typeof(int)));

// populate DataTable from your List here
foreach(var id in employeeIds)
    tvp.Rows.Add(id);

using (conn)
{
    SqlCommand cmd = new SqlCommand("dbo.DoSomethingWithEmployees", conn);
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter tvparam = cmd.Parameters.AddWithValue("@List", tvp);
    // these next lines are important to map the C# DataTable object to the correct SQL User Defined Type
    tvparam.SqlDbType = SqlDbType.Structured;
    tvparam.TypeName = "dbo.IDList";
    // execute query, consume results, etc. here
}

SQL Server 2005

Om du använder SQL Server 2005, skulle jag fortfarande rekommendera en delad funktion över XML. Skapa först en funktion:

CREATE FUNCTION dbo.SplitInts
(
   @List      VARCHAR(MAX),
   @Delimiter VARCHAR(255)
)
RETURNS TABLE
AS
  RETURN ( SELECT Item = CONVERT(INT, Item) FROM
      ( SELECT Item = x.i.value('(./text())[1]', 'varchar(max)')
        FROM ( SELECT [XML] = CONVERT(XML, '<i>'
        + REPLACE(@List, @Delimiter, '</i><i>') + '</i>').query('.')
          ) AS a CROSS APPLY [XML].nodes('i') AS x(i) ) AS y
      WHERE Item IS NOT NULL
  );
GO

Nu kan din lagrade procedur bara vara:

CREATE PROCEDURE dbo.DoSomethingWithEmployees
  @List VARCHAR(MAX)
AS
BEGIN
  SET NOCOUNT ON;

  SELECT EmployeeID = Item FROM dbo.SplitInts(@List, ','); 
END
GO

Och i din C#-kod behöver du bara skicka listan som '1,2,3,12' ...

Jag tycker att metoden att passera genom tabellvärderade parametrar förenklar underhållet av en lösning som använder den och har ofta ökad prestanda jämfört med andra implementeringar inklusive XML och strängdelning.

Ingångarna är tydligt definierade (ingen behöver gissa om avgränsaren är ett kommatecken eller semikolon) och vi har inga beroenden av andra bearbetningsfunktioner som inte är uppenbara utan att inspektera koden för den lagrade proceduren.

Jämfört med lösningar som involverar användardefinierat XML-schema istället för UDT:er, innebär detta ett liknande antal steg men enligt min erfarenhet är det mycket enklare kod att hantera, underhålla och läsa.

I många lösningar behöver du kanske bara en eller några av dessa UDT:er (User defined Types) som du återanvänder för många lagrade procedurer. Precis som i det här exemplet är det vanliga kravet att gå igenom en lista med ID-pekare, funktionsnamnet beskriver vilket sammanhang dessa ID ska representera, typnamnet ska vara generiskt.



  1. MySQL:Välj alla datum inom ett intervall även om inga poster finns

  2. Ansible älskar PostgreSQL

  3. 5 SQL-syntax och frågeprinciper för bättre databasövervakning

  4. Datareplikering i IRI Workbench