views:

42

answers:

3

We're using SQL Server 2000 Query Analyser, and one issue we have is that very occasionally, when a user is updating our live database, they insert the incorrect/no(!) where clause. I know, not good, but it happens.

Are there any editors that will warn of the number of rows that might be changed (if that is even possible) or even a way to configure an editor, if it is connected to a certain database, to prompt for confirmation before the query is run?

We have a way to recover our data in the cases where we run an incorrect query, but it takes time, and I'm just seeing if there are any ways to catch the error, or at least give the user a second chance.

Thanks in advance.

+2  A: 

One approach is to create a template that wraps statements in a transaction, and rollback at the end. That way you can see affected rows and undo.

If you install the SQL Server Management Studio Tools Pack, then the default behaviour (configurable) when clicking on 'New Query...' is to open a window with

BEGIN TRAN



ROLLBACK

in it.

Mitch Wheat
Thanks, but that's not going to be very 'automatic'. Is there anything that might be implicit with running the query?
Ciaran Archer
see my update for an automatic approach
Mitch Wheat
but won't the user be able to just delete those line of code off the screen?
KM
They're not going to pay any attention to a prompt either, except maybe the first few times they see it.
CodeByMoonlight
'SQL Server Management Studio Tools Pack' isn't going to work for me using SQL Server 2000. But I wish it was available for SQL Server 2000. I'd kill for the connection colour coding alone.
Ciaran Archer
+3  A: 

The only way is to not to let user edit data using SQL Server 2000 Query Analyser! But then you'll have to write an application and control the data, and you can then issue warnings as necessary.

Short of that, you could add triggers to every table and set some sort limit where you issue a ROLLBACK if the rows affected is greater than X. You could even use something like SUSER_NAME() to apply the limit to certain users.

sample trigger:

CREATE TRIGGER Trigger_YourTable ON YourTable
FOR INSERT, UPDATE, DELETE
AS
DECLARE @Limit    int
DECLARE @Message  varchar(100)
SET @Limit=5
SET @Message='ERROR, Not Permitted to alter more than '+CONVERT(varchar(5),@Limit)+' rows at any one time.'

IF SUSER_NAME() !='AwesomeSA'
BEGIN
    IF @Limit<(SELECT COUNT(*) FROM INSERTED)
    BEGIN
        ROLLBACK
        RAISERROR(@Message, 16, 1);
        RETURN
    END
    ELSE IF @Limit<(SELECT COUNT(*) FROM DELETED)
    BEGIN
        ROLLBACK
        RAISERROR(@Message, 16, 1);
        RETURN
    END
END

GO

to automatically generate all the triggers scripts run this (does not actually add them in the database, just produce the text script which you should edit and then run):

DECLARE @SQL varchar(8000)
SET @SQL='PRINT ''CREATE TRIGGER [''+REPLACE(REPLACE(REPLACE(''Trigger_?'',''['',''''),'']'',''''),''.'',''_'')+''] ON ?''; PRINT ''FOR INSERT, UPDATE, DELETE
AS
DECLARE @Limit    int
DECLARE @Message  varchar(50)
SET @Limit=5
SET @Message=''''ERROR, Not Permitted to alter more than ''''+CONVERT(varchar(5),@Limit)+'''' rows at any one time.''''

IF SUSER_NAME() !=''''AwesomeSA''''
BEGIN
    IF @Limit<(SELECT COUNT(*) FROM INSERTED)
    BEGIN
        ROLLBACK
        RAISERROR(@Message, 16, 1);
        RETURN
    END
    ELSE IF @Limit<(SELECT COUNT(*) FROM DELETED)
    BEGIN
        ROLLBACK
        RAISERROR(@Message, 16, 1);
        RETURN
    END
END
GO'''
EXEC sp_msforeachtable @SQL

all tables will have an affected row limit of 5 unless you login as user "AwesomeSA". The above script will generate the code, not actually create the triggers. You can edit the output of this script, setting good row limits, users, etc. and then run that script and then the triggers will be created.

KM
That's an interesting 'table-side' approach.
Ciaran Archer
you can't do anything to limit SQL Server 2000 Query Analyser, you don't have the source code and there isn't and warning provision. If you can't/don't want to write your own application to control the users data edits, then your **only** method is to control the tables with triggers.
KM
+1  A: 

To take Mitch Wheat's answer and expand I've used this with success. If I was going to use this regularly I'd make a stored procedure that would take the expected row count, from statement and where statement as input and automate the entire thing.

begin tran

declare @err int
declare @cnt int

-- select total count of records to be deleted 
select @cnt = count(*)
  from dbo.table
 where delete_ind = 1    

-- show that in the results pane
select 'Count', @cnt

-- Delete it (note that the from and where statements are the same from count query)
Delete
  from dbo.table
 where delete_ind = 1

select @err = @@error

if @err <> 0  --check to see if query failed
BEGIN
   -- Return 99 to the calling program to indicate failure.
   raiserror('An error occurred deleting from dbo.table.',16,1)
   ROLLBACK
END     
ELSE if @cnt = 1168730  --yes this is a hard coded expected row count
BEGIN
   raiserror('Delete processed %i rows from dbo.table.',1,1,@cnt)
   COMMIT
END
CTKeane