Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Трябва ли тук да се използват параметри със стойност на таблица?

Да, използвайте параметри със стойност на таблица. Първо създайте тип:

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

Сега вашата процедура може да използва това (имайте предвид, че промених вашия вложен IN заявки за правилно присъединяване):

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

И вашият C# код ще премине в DataTable или както сте събрали колекцията от activeIds, а не списък, разделен със запетаи.

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. ...

Ако искате да настоявате за предаване на низ в съхранената процедура, ще трябва да използвате функция за разделяне. Например:

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

Сега вашата съхранена процедура може да бъде:

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. SQL заявка за групиране по ден

  2. Динамичен SQL (предаване на името на таблицата като параметър)

  3. Как да изберете определен брой символи отляво или отдясно на низ в SQL Server

  4. Липсващ артефакт com.microsoft.sqlserver:sqljdbc4:jar:4.0

  5. Върнете изходен параметър на съхранена процедура в друга съхранена процедура