我们正在使用SQL Server 2000查询分析器,我们遇到的一个问题是偶尔,当用户更新我们的实时数据库时,他们会插入错误的/ no(!)where
子句。我知道,不好,但它发生了。
是否有任何编辑器会警告可能会更改的行数(如果可能的话)或者甚至是配置编辑器的方法(如果它连接到某个数据库),以便在编辑之前提示确认查询是否运行?
我们有办法在运行错误查询的情况下恢复数据,但这需要时间,我只是看看是否有任何方法可以捕获错误,或者至少给用户一秒钟机会。
提前致谢。
答案 0 :(得分: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。上面的脚本将生成代码,而不是实际创建触发器。您可以编辑此脚本的输出,设置良好的行限制,用户等,然后运行该脚本,然后创建触发器。
答案 1 :(得分:2)
一种方法是创建一个包装事务中的语句的模板,并在最后回滚。这样您就可以看到受影响的行并撤消。
如果您安装了SQL Server Management Studio Tools Pack,那么点击“新建查询...”时的默认行为(可配置)就是打开一个带有
的窗口BEGIN TRAN
ROLLBACK
在其中。
答案 2 :(得分:1)
采取Mitch Wheat的答案并扩展我已经成功地使用了它。如果我要定期使用它,我会创建一个存储过程,该过程将采用预期的行数,从statement和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