用于填充“IN”子句的参数

时间:2013-09-06 13:11:38

标签: sql tsql stored-procedures ms-access-2007

在此过程中,用户传递一个项目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

5 个答案:

答案 0 :(得分:1)

在此信息中查看所选答案:How to pass string parameter with `IN` operator in stored procedure SQL Server 2008

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

答案 1 :(得分:1)

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

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

  Where [Somecolumn] In (Select funcColName From dbo.ConvertFunction(@stringParameter))

答案 2 :(得分:1)

我能够将多个值传递给存储过程的唯一方法是将它们连接到字符串并将字符串传递给SP,然后在SP的开头解析字符串,类似这样(projetc_id的被删除了,

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

答案 3 :(得分:0)

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

答案 4 :(得分: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表时生成唯一标识符,然后在执行存储过程时对该标识符进行过滤。