1

在此过程中,用户传递一个项目 ID。我希望能够传递不确定数量的项目 ID,以便我可以将 where 子句从“ProjectID=@projectID”(例如)更改为“ProjectID IN (@ProjectID)”。

这样,我可以通过一次调用数据库来删除十几个项目,而不是重复调用数据库。

有没有一个好的策略来做到这一点?我正在从 Access 调用 SP....

create procedure dbo.cpas_DeleteProject
@ProjectID INt = 0,
@errorFlag int OUTPUT
AS
set @errorFlag=0
BEGIN TRY
    BEGIN TRANSACTION
        DELETE FROM tblWOTasks WHERE tblWOTasks.WorkOrderID IN (SELECT ID FROM tblWorkOrders WHERE ProjectID=@ProjectID)
        DELETE FROM tblELaborSpread WHERE tblELaborSpread.WorkOrderID IN (SELECT ID FROM tblWorkOrders WHERE ProjectID=@ProjectID)
        DELETE FROM tblWorkOrders WHERE tblWorkOrders.ProjectID IN (SELECT ID FROM tblWorkOrders WHERE ProjectID=@ProjectID)
        DELETE FROM tblCPTransactiON WHERE tblCPTransactiON.CPProjectID=@ProjectID
        DELETE FROM tblCPJE WHERE tblcpje.jeid IN 
            (SELECT tblcpje.JEID FROM tblCPJE left joIN tblCPTransactiON as CR ON CR.CPTransID = tblCPJE.JECreditID 
                            left joIN tblCPTransactiON as DR ON DR.CPTransID = tblCPJE.JEDebitID 
                    WHERE DR.CPTransID is null AND cr.CPTransID is null)        
        DELETE FROM tblProjectTasks WHERE tblProjectTasks.ProjectID=@ProjectID
        DELETE FROM xrefProjectMICAP WHERE xrefProjectMICAP.ProjectID=@ProjectID
        DELETE FROM tblworkorders WHERE tblWorkOrders.ProjectID=@ProjectID
        DELETE FROM tblprojects WHERE tblProjects.ID=@ProjectID
        --Project Comments cascade delete....
    COMMIT TRANSACTION
END TRY

BEGIN CATCH
    ROLLBACK TRANSACTION
    set @errorFlag=1
END CATCH
4

5 回答 5

1

查看这篇文章中的选定答案:如何在存储过程 SQL Server 2008 中使用 `IN` 运算符传递字符串参数

用户所做的是创建一个存储过程,它将逗号分隔的字符串分开,然后返回一个表。获得 ID 表后,您可以将其插入查询中。由于您的查询包含更多查询,因此可能需要进行一些修改才能使其正常工作,但理论仍然相同。

于 2013-09-06T13:18:16.873 回答
1

如果您不能使用表参数,则创建一个分隔字符串参数来保存多个 Id 值并将该分隔字符串转换为 proc 内的表变量。(网上有很多 T-SQL UDF 可以做到这一点。一篇好文章就是这篇。)

然后您的 In 子句将如下所示:

  Where [Somecolumn] In (Select funcColName From dbo.ConvertFunction(@stringParameter))
于 2013-09-06T13:18:52.090 回答
1

The only way I have been able to pass multible values to a stored procedure is to concat them to a string and pass the string to the SP and then parse the string in the beginning of the SP, something like this (the projetc_id's are delimeted with ,

CREATE PROCEDURE [dbo].[cpas_DeleteProject] 

@ProjectID varchar(3000)
@errorFlag int OUTPUT
AS

--Parse function
DECLARE @tblstring Table(ProjectID int) --table variable to store all parsed ProjectID's
DECLARE @project varchar(10)

DECLARE @StartPos int, 
@Length int,--streng lengd
@Delimeter varchar(1)=','--delimeter
WHILE LEN(@ProjectID) > 0
  BEGIN
   SET @StartPos = CHARINDEX(@Delimeter, @ProjectID)
IF @StartPos < 0 SET @StartPos = 0
SET @Length = LEN(@ProjectID) - @StartPos - 1
IF @Length < 0 SET @Length = 0
IF @StartPos > 0
  BEGIN
    SET @Project = SUBSTRING(@ProjectID, 1, @StartPos - 1)
    SET @ProjectID = SUBSTRING(@ProjectID, @StartPos + 1, LEN(@ProjectID) - @StartPos)
  END
ELSE
  BEGIN
    SET @Project = @ProjectID
    SET @ProjectID = ''
  END
INSERT @tblstring (ProjectID) VALUES(@Project)
END


     set @errorFlag=0
BEGIN TRY
BEGIN TRANSACTION
    DELETE FROM tblWOTasks WHERE tblWOTasks.WorkOrderID IN (SELECT ID FROM tblWorkOrders WHERE ProjectID in (SELECT ProjectID  from @tblstring))
    DELETE FROM tblELaborSpread WHERE tblELaborSpread.WorkOrderID IN (SELECT ID FROM tblWorkOrders WHERE ProjectID in (SELECT ProjectID  from @tblstring))
    DELETE FROM tblWorkOrders WHERE tblWorkOrders.ProjectID IN (SELECT ID FROM tblWorkOrders WHERE ProjectID in (SELECT ProjectID  from @tblstring))
    DELETE FROM tblCPTransactiON WHERE tblCPTransactiON.CPProjectID in (SELECT ProjectID  from @tblstring)
    DELETE FROM tblCPJE WHERE tblcpje.jeid IN 
        (SELECT tblcpje.JEID FROM tblCPJE left joIN tblCPTransactiON as CR ON CR.CPTransID = tblCPJE.JECreditID 
                        left joIN tblCPTransactiON as DR ON DR.CPTransID = tblCPJE.JEDebitID 
                WHERE DR.CPTransID is null AND cr.CPTransID is null)        
    DELETE FROM tblProjectTasks WHERE tblProjectTasks.ProjectID in (SELECT ProjectID  from @tblstring)
    DELETE FROM xrefProjectMICAP WHERE xrefProjectMICAP.ProjectID in (SELECT ProjectID  from @tblstring)
    DELETE FROM tblworkorders WHERE tblWorkOrders.ProjectID in (SELECT ProjectID  from @tblstring)
    DELETE FROM tblprojects WHERE tblProjects.ID in (SELECT ProjectID  from @tblstring)
    --Project Comments cascade delete....
COMMIT TRANSACTION
END TRY

BEGIN CATCH
ROLLBACK TRANSACTION
set @errorFlag=1
END CATCH
于 2013-09-06T13:29:09.260 回答
0

您可以查看使用表值参数...

于 2013-09-06T13:15:44.077 回答
0

尽管可以在 SQL Server 中使用表值参数,但据我所知,从 Access 填充这些参数并不容易。

一种解决方案可能是在存储过程中使用动态 SQL,然后将项目 ID 放在 Access 应用程序中创建的 varchar(max) 中,例如:

@projectIdList = '200,300,400'

然后在您的动态 SQL 中,您只需将其包含为

'WHERE tblProjects.ID IN (' + @projectIdList + ')'

这显然容易受到 SQL 注入攻击,但根据您的 Access 应用程序的使用方式,这可能是可以接受的。

另一个更安全的解决方案是允许 Access 在调用存储过程之前将 projectId 写为小表中的行,然后在存储过程中执行如下删除操作:

DELETE FROM tblprojects 
WHERE tblProjects.ID IN (SELECT ProjectId FROM ProjectIdsToBeDeleted)

这更加安全和清洁,因为您避免了动态 SQL。但是,您需要某种方法来处理并发 - 可能通过在填充 ProjectIdsToBeDeleted 表时生成唯一标识符,然后在执行存储过程时过滤该相同标识符。

于 2013-09-06T13:17:32.883 回答