1

我们正在使用 SQL Server 2000 查询分析器,我们遇到的一个问题是,当用户更新我们的实时数据库时,他们偶尔会插入不正确的/no(!)where子句。我知道,不好,但它发生了。

是否有任何编辑器会警告可能更改的行数(如果可能的话),甚至是配置编辑器的方法,如果它连接到某个数据库,则在运行查询之前提示确认?

在我们运行错误查询的情况下,我们有办法恢复我们的数据,但这需要时间,我只是看看是否有任何方法可以捕获错误,或者至少给用户第二次机会。

提前致谢。

4

3 回答 3

3

唯一的办法是不要让用户使用 SQL Server 2000 查询分析器编辑数据! 但是您必须编写一个应用程序并控制数据,然后您可以根据需要发出警告。

除此之外,您可以向每个表添加触发器并设置某种排序限制,如果受影响的行大于 X,则在其中发出 ROLLBACK。您甚至可以使用SUSER_NAME()之类的东西将限制应用于某些用户。

示例触发器:

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

自动生成所有触发器脚本运行这个(实际上并不将它们添加到数据库中,只需生成您应该编辑然后运行的文本脚本):

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

除非您以用户“AwesomeSA”身份登录,否则所有表的受影响行数限制为 5。上面的脚本将生成代码,而不是实际创建触发器。您可以编辑此脚本的输出,设置好的行限制、用户等,然后运行该脚本,然后将创建触发器。

于 2010-03-31T12:00:59.437 回答
2

一种方法是创建一个模板,将语句包装在事务中,并在最后回滚。这样您就可以看到受影响的行并撤消。

如果您安装SQL Server Management Studio Tools Pack,则单击“新查询...”时的默认行为(可配置)是打开一个窗口

BEGIN TRAN



ROLLBACK

在里面。

于 2010-03-31T08:56:09.980 回答
1

为了接受 Mitch Wheat 的回答并扩展,我已经成功地使用了它。如果我要定期使用它,我会创建一个存储过程,它将预期的行数、from 语句和 where 语句作为输入并自动化整个事情。

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
于 2010-03-31T12:15:00.903 回答