如果从Trigger vs Manual执行,则存储过程会返回不同的结果

时间:2010-12-03 23:16:15

标签: sql sql-server stored-procedures triggers

我有一个存储过程,用另一个表中的数据填充表。 当我使用Update Trigger执行SP 3时,会将记录插入表中。

如果我手动执行SP,我会在表格中获得6条记录。

 'SET ANSI_NULLS ON', 
 'SET QUOTED_IDENTIFIER ON', 
 'SET NOCOUNT ON' 
SP和触发器中的

相同。

这是SP:

 SET ANSI_NULLS ON
 GO
 SET QUOTED_IDENTIFIER ON
 GO
 -- =============================================
 -- Author:     
 -- Create date: 
 -- Description:    
 -- =============================================
 ALTER PROCEDURE [dbo].[Residency_Date_Summary_Populate]
-- Add the parameters for the stored procedure here

 AS
 BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

 DECLARE @StartDate datetime;
 SET @StartDate = DateAdd(year, DateDiff(year, 0, GetDate()), 0);

 WITH Tally (N) AS 
 (SELECT TOP (12) ROW_NUMBER() OVER (ORDER BY (SELECT 0))
 FROM master.sys.objects), CTE1 AS
 (SELECT c.First_Name,
   c.Last_Name,
   c.ID,
    r.Building,       
   r.Move_In_Date,
   r.Move_Out_Date,
   StartOfMonth = DateAdd(month, t1.N-1, @StartDate),
   EndOfMonth   = DateAdd(day, -1, DateAdd(month, t1.N, @StartDate)),
   MonthNbr = t1.N
 FROM CONTACTS c
   JOIN Residency_Dates r
     ON c.ID = r.ID_U       
   JOIN Tally t1
     ON t1.N between month(r.move_in_date) and month(coalesce( r.move_out_date,        getdate  ()))), CTE2 AS
  ( SELECT First_Name,
   Last_Name,
   Building,
   MonthNbr,
   ID
   ,StayForMonth = CASE WHEN Move_In_Date > StartOfMonth AND Move_out_Date <=      EndOfMonth 
    THEN DateDiff(day, Move_In_Date, Move_Out_Date)
         WHEN Move_In_Date > StartOfMonth 
    THEN DateDiff(day, Move_In_Date, EndOfMonth)
         WHEN Move_out_Date > EndOfMonth 
    THEN DateDiff(day, StartOfMonth, EndOfMonth) 
         WHEN Move_out_Date IS NULL AND month(StartOfMonth) = month(GetDate())
    THEN DateDiff(day, StartOfMonth, GetDate())
         ELSE DateDiff(day, StartOfMonth, COALESCE(Move_Out_Date, EndOfMonth)) 
    END    
 FROM CTE1)
 INSERT into Residency_Date_Summary

 SELECT First_Name,
   Last_Name,
   Building,
   January = MAX(CASE WHEN MonthNbr = 1 THEN StayForMonth ELSE 0 END),
   February = MAX(CASE WHEN MonthNbr = 2 THEN StayForMonth ELSE 0 END),
   March = MAX(CASE WHEN MonthNbr = 3 THEN StayForMonth ELSE 0 END),
   April = MAX(CASE WHEN MonthNbr = 4 THEN StayForMonth ELSE 0 END),
   May = MAX(CASE WHEN MonthNbr = 5 THEN StayForMonth ELSE 0 END),
   June = MAX(CASE WHEN MonthNbr = 6 THEN StayForMonth ELSE 0 END),
   July = MAX(CASE WHEN MonthNbr = 7 THEN StayForMonth ELSE 0 END),
   August = MAX(CASE WHEN MonthNbr = 8 THEN StayForMonth ELSE 0 END),
   September = MAX(CASE WHEN MonthNbr = 9 THEN StayForMonth ELSE 0 END),
   October = MAX(CASE WHEN MonthNbr = 10 THEN StayForMonth ELSE 0 END),
   November = MAX(CASE WHEN MonthNbr = 11 THEN StayForMonth ELSE 0 END),
   December = MAX(CASE WHEN MonthNbr = 12 THEN StayForMonth ELSE 0 END)
 FROM CTE2  
 GROUP BY First_Name, Last_Name, Building
 ORDER BY Last_Name, First_Name, Building;

End

1 个答案:

答案 0 :(得分:2)

问题是您用于生成数字计数表的代码

WITH Tally (N) AS 
(SELECT TOP (12) ROW_NUMBER() OVER (ORDER BY (SELECT 0)) FROM master.sys.objects)

当我以具有有限权限的用户身份登录时select * FROM master.sys.objects仅返回6个项目,而以sa登录时返回82个项目。因此,您的计数表只有6个项目,而不是您在某些登录项下运行时所期望的12项。

坦率地说,将登录添加到sysadmin组的“修复”是荒谬的。如果另一个登录触发了触发器,并且如果您的应用程序有任何SQL注入漏洞,并且登录系统管理员权限将允许攻击者做任何事情,那么您仍然会遇到问题。

您需要做的就是替换

WITH Tally (N) AS 
 (SELECT TOP (12) ROW_NUMBER() OVER (ORDER BY (SELECT 0))
 FROM master.sys.objects), CTE1 AS
 (SELECT c.First_Name,
   c.Last_Name,

WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
     E02(N) AS (SELECT 1 FROM E00 a, E00 b),
     E04(N) AS (SELECT 1 FROM E02 a, E02 b),
     Tally (N) AS (SELECT TOP (12) ROW_NUMBER() OVER (ORDER BY (SELECT 0)) FROM E04), 
     CTE1 AS
 (SELECT c.First_Name,
   c.Last_Name,