Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Czy należy tutaj używać parametrów wycenianych w tabeli?

Tak, użyj parametrów wycenianych w tabeli. Najpierw utwórz typ:

CREATE TYPE dbo.StudentIDs(ID INT PRIMARY KEY);

Teraz twoja procedura może tego użyć (zauważ, że zmieniłem twoje zagnieżdżone IN zapytania do prawidłowego sprzężenia):

CREATE PROCEDURE dbo.MarkStudentsAsDeleted
  @IDs dbo.StudentIDs READONLY
AS
BEGIN
  SET NOCOUNT ON;

  UPDATE s SET IsDeleted = 1
    FROM dbo.Students AS s
    INNER JOIN dbo.Class AS c
    ON s.StudentId = c.StudentId
    INNER JOIN dbo.ClassValueTable AS ct
    ON c.PassId = ct.Id
    WHERE ct.IsDeleted <> 1
    AND EXISTS (SELECT 1 FROM @IDs WHERE StudentID = s.StudentID);
END 
GO

A Twój kod C# przekazałby w DataTable lub w inny sposób, w jaki zebrałeś kolekcję activeIds, a nie listę rozdzielaną przecinkami.

DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Rows.Add(1);
dt.Rows.Add(2);
dt.Rows.Add(3);
dt.Rows.Add(4);

... open connection etc. ...

SqlCommand cmd = new SqlCommand("dbo.MarkStudentsAsDeleted", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvp1 = cmd.Parameters.AddWithValue("@IDs", dt);
tvp1.SqlDbType = SqlDbType.Structured;
cmd.ExecuteNonQuery();

... close, dispose, etc. ...

Jeśli chcesz nalegać na przekazywanie łańcucha do procedury składowanej, musisz użyć funkcji split. Na przykład:

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

Teraz Twoja procedura składowana może być:

CREATE PROCEDURE dbo.MarkStudentsAsDeleted
  @IDs VARCHAR(MAX)
AS
BEGIN
  SET NOCOUNT ON;

  UPDATE s SET IsDeleted = 1
    FROM dbo.Students AS s
    INNER JOIN dbo.Class AS c
    ON s.StudentId = c.StudentId
    INNER JOIN dbo.ClassValueTable AS ct
    ON c.PassId = ct.Id
    WHERE ct.IsDeleted <> 1
    AND EXISTS (SELECT 1 FROM dbo.SplitInts(@IDs, ',') WHERE Item = s.StudentID);
END 
GO



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Konwersja Unicode do Non-Unicode

  2. Wybierz pierwsze n rekordów dla każdego odrębnego identyfikatora w SQL Server 2008

  3. SSRS wyświetla tylko pierwszy wiersz

  4. Aktualizacja SQL, to samo zapytanie, za każdym razem inne wyniki

  5. Jak oddzielić datę od napisu?