2010-12-03 23 views
0

J'ai une procédure stockée qui remplit une table avec des données d'une autre table. Lorsque j'utilise un déclencheur de mise à jour pour exécuter les enregistrements SP 3 sont insérés dans la table.La procédure stockée renvoie des résultats différents si elle est exécutée à partir de Trigger par rapport à Manual

Si j'exécute le SP manuellement, j'obtiens 6 enregistrements dans le tableau.

'SET ANSI_NULLS ON', 
'SET QUOTED_IDENTIFIER ON', 
'SET NOCOUNT ON' 

sont identiques dans SP et Trigger.

C'est le 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

est-il de la même connexion utilisé? A-t-il des permissions sur 'sys.objects'? –

Répondre

2

Le problème est le code que vous utilisez pour générer une table de pointage des numéros

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

Lorsque je me connecte en tant qu'utilisateur avec des autorisations limitées select * FROM master.sys.objects retours seulement 6 articles par rapport à 82 en étant connecté en tant que sa. Par conséquent, votre table de pointage ne comportera que 6 éléments et non les 12 que vous attendiez lors de certaines connexions.

Votre «solution» d'ajouter le login au groupe sysadmin est, franchement, ridicule. Vous obtiendrez toujours le problème si une autre connexion déclenche le déclencheur et si votre application a des vulnérabilités d'injection SQL donnant les droits sysadmin de connexion permettra à l'attaquant de faire à peu près tout.

Tout ce que vous devez faire est de remplacer

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, 

avec

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, 
+0

Je suis désolé, mais je ne comprends pas très bien votre réponse. Voulez-vous dire que l'utilisateur de la base de données a trop d'autorisations attribuées? – Stan

+0

@Stan - Non. Je dis votre morceau de code 'avec Tally (N) AS (SELECT TOP (12) ROW_NUMBER() OVER (ORDER BY (SELECT 0)) FROM master.sys.objects)' ne sera pas fonctionne comme prévu en générant une table de nombres de 1 à 12 si moins de 12 lignes sont renvoyées par cette requête. Le nombre de lignes renvoyées dépendra des autorisations. –

+0

@Martin - Merci pour votre aide. Je comprends un peu ce que vous dites ... mon expérience SQL est très limitée et je ne comprends pas trop ce que vous voulez dire ... s'il vous plaît, supportez-moi. Comment puis-je corriger le code pour tirer parti de votre exemple? J'ai essayé de mettre à jour, en utilisant votre exemple, mais je n'ai pas réussi à le faire correctement. – Stan