68

Ok, so my schema is this:

Table: Timesheet_Hours

Columns:

  • Timesheet_Id (PK, int)
  • Staff_Id (int)
  • BookedHours (int)
  • Posted_Flag (boolean)

This is an extremely simplified version of the table, but it will serve for the purposes of this explaination. Assume that a person can only ever have one timesheet record.

What I'm trying to do is add records to another table, called WorkLog. Each record here has a time associated with it. When that table is updated, I want to update Timesheet_Hours as well.

Before I update Timesheet_Hours, I want to check first that the relevant Timesheets haven't already been posted, and then I want to check if there is in fact a record to update in the first place.

The first part of the if statement, which checks to see that the timesheets haven't already been posted, works fine. The problem is the second part. It is checking to see that the record it is going to update already exists. The issue is that it always raises an error.

NB: The code below is extracted from a stored procedure run by the update, insert and delete triggers on the WorkLog table. @PersonID is one of the parameters to that table. The stored procedure works fine if I comment out the second part of this statement.

IF EXISTS
    (
    SELECT 1
    FROM Timesheet_Hours
    WHERE Posted_Flag = 1
    AND Staff_Id = @PersonID
    )

    BEGIN
        RAISERROR('Timesheets have already been posted!', 16, 1)
        ROLLBACK TRAN
    END
ELSE
    IF NOT EXISTS
        (
        SELECT 1
        FROM Timesheet_Hours
        WHERE Staff_Id = @PersonID
        )

        BEGIN
            RAISERROR('Default list has not been loaded!', 16, 1)
            ROLLBACK TRAN
        END
Ryan Kirkman
  • 4,051
  • 2
  • 25
  • 20
  • Is 1 a name of a column in your Timesheet_Hours table? – SirDemon Jul 24 '09 at 00:38
  • 1
    No, it is not. As I'm using EXISTS, I was just following what I thought was standard practice in sub-queries using EXISTS. – Ryan Kirkman Jul 24 '09 at 00:41
  • 2
    1 in that case is just a constant. All he cares about is that a row is returned, not the value of any columns. Using a constant is usually faster than using * or a specific column list. – Rick Jul 24 '09 at 00:44
  • 'if not exists()' is working just fine. It's your use of it that may be questionable. You may want to title your question something like 'How do I use SQL Server IF NOT EXISTS?' instead. – yfeldblum Jul 24 '09 at 01:06
  • 1
    Done, as per your suggestion Justice. – Ryan Kirkman Jul 24 '09 at 01:33

1 Answers1

75

Have you verified that there is in fact a row where Staff_Id = @PersonID? What you've posted works fine in a test script, assuming the row exists. If you comment out the insert statement, then the error is raised.

set nocount on

create table Timesheet_Hours (Staff_Id int, BookedHours int, Posted_Flag bit)

insert into Timesheet_Hours (Staff_Id, BookedHours, Posted_Flag) values (1, 5.5, 0)

declare @PersonID int
set @PersonID = 1

IF EXISTS    
    (
    SELECT 1    
    FROM Timesheet_Hours    
    WHERE Posted_Flag = 1    
        AND Staff_Id = @PersonID    
    )    
    BEGIN
        RAISERROR('Timesheets have already been posted!', 16, 1)
        ROLLBACK TRAN
    END
ELSE
    IF NOT EXISTS
        (
        SELECT 1
        FROM Timesheet_Hours
        WHERE Staff_Id = @PersonID
        )
        BEGIN
            RAISERROR('Default list has not been loaded!', 16, 1)
            ROLLBACK TRAN
        END
    ELSE
        print 'No problems here'

drop table Timesheet_Hours
Rick
  • 4,575
  • 1
  • 26
  • 20
  • Thanks mate. It turned out I wasn't passing the correct PersonID from the INSERT trigger. It was confusing me because it was working with the UPDATE and DELETE triggers, but I didn't think to check the parameters. – Ryan Kirkman Jul 24 '09 at 01:01