紧张的运行查询(SQL Server):您对此有何看法?

紧张的运行查询(SQL Server):您对此有何看法?,sql,sql-server,transactions,Sql,Sql Server,Transactions,我经常使用SQLServerManagementStudio。有时,我会遇到需要运行更新或删除查询的情况,但我担心我的某些输入错误或逻辑错误会导致我对表进行不必要的大量更改(例如,当我打算更改2时更改1000行) 过去,我只会握紧拳头屏住呼吸,但后来我想知道,在一个可能是灾难性的询问之前,我是否可以这样做: 1) 跑下 begin transaction (my update/insert/delete statement I want to run) 2) 如果我满意,请致电: commit

我经常使用SQLServerManagementStudio。有时,我会遇到需要运行更新或删除查询的情况,但我担心我的某些输入错误或逻辑错误会导致我对表进行不必要的大量更改(例如,当我打算更改2时更改1000行)

过去,我只会握紧拳头屏住呼吸,但后来我想知道,在一个可能是灾难性的询问之前,我是否可以这样做:

1) 跑下

begin transaction
(my update/insert/delete statement I want to run)
2) 如果我满意,请致电:

commit transaction
3) 或者,如果我把事情弄糟了,就打电话:

rollback transaction
我的想法是正确的,还是我遗漏了一些基本的东西?我知道我可以随时恢复我的数据库,但与上面的相比,这似乎有些过头了

编辑:

1) 我同意在做任何事情之前先在测试站点上进行测试,但在生产服务器上仍然有可能发生问题。可能测试服务器上的某些条件是正确的,而生产服务器上的某些条件不是正确的


2) 我也习惯于写我的where first,或者用where first进行选择以确保我隔离了正确的行,但同样,总会出现一些问题。

是的,你绝对可以这样做。请注意,您正在对有问题的表进行锁定,这可能会干扰其他数据库活动。

这种担心最常见的原因是被迫手动处理生产数据库。如果是这样的话…最好买一些开发工具盒。如果没有,我想你很好…

听起来很不错-我基本上使用这个默认的try/catch查询来完成大部分的繁重工作;工作原理与您绘制的一样,并且如果出现问题,它会为您提供错误信息:

BEGIN TRANSACTION
BEGIN TRY

    -- do your work here

    COMMIT TRANSACTION

END TRY
BEGIN CATCH
    SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage

    ROLLBACK TRANSACTION
END CATCH

Marc

在将WHERE语句作为UPDATE或DELETE运行之前,请先将其作为SELECT运行

您可以做的另一件事是:始终先编写WHERE子句,这样您就不必担心在所有行上运行UPDATE或DELETE。

这条特定语句至少两次保存了我的屁股

SELECT * INTO Table2_Backup FROM Table1

我也完全同意马努的观点。选择更新之前或删除之前

以下是我在编写要从查询窗口运行的文本时所做的操作,我这样做是为了修复导入中从客户端发送给我们的坏数据(我总是先在dev上执行此操作)

开始传输
删除mt
--选择*
从mytable mt何处开始
--提交传输
--回滚传输
开始事务
更新机器翻译
设置myfield=replace(myfield,'some random text','some other random text'
--选择myid、myfield、replace(myfield、一些随机文本、一些其他随机文本)
从mytable mt何处开始
--提交传输
--回滚传输
请注意,通过这种方式,我可以运行查询的select部分,首先查看将受影响的记录以及如何受影响。请注意where子句与表位于同一行(如果我有多个连接,则为最后一个连接)这防止了oops我忘记突出显示整个问题。请注意,delete使用了一个别名,因此如果您意外地只运行第一行,则不会删除整个表

我发现最好是编写脚本,这样它们就可以在不突出显示的情况下运行(除非我只突出显示所选部分以查看我影响的记录)。将脚本保存在源代码管理中。如果您通过在dev和QA上运行来测试tscript,则可以在prod上运行它,而不使用selects。如果您影响表上的大型更新或删除,我几乎总是先将这些记录复制到工作表中,以便在出现问题时可以立即返回。

如果您愿意的话(或者必须)对此非常偏执,您应该为旧/新val创建某种日志表(表/列/旧val/新val;可能是用户和时间戳)并在插入/更新/删除时使用触发器填充。从中恢复一些旧值确实很麻烦,但如果其他所有操作都出现严重错误,则可能会有所帮助。不过,这会对性能产生相当大的影响


SAP使用这种方法(SAP术语中称为change docs)通过其GUI进行更改,并为程序员提供了一种通过“程序”进行更改的方法(尽管您必须明确地调用它).

在生产环境中运行查询之前,您是否可以在较低的环境中进行测试?我完全同意Paul的观点。设置一个测试环境,以便您可以准确地看到运行脚本时会发生什么。这可能吗?我认为“友好的it环境”与测试环境无关,如果您正在运行potte,您需要一个测试环境对生产数据进行非常危险的查询,您不能随意使用,然后您需要100%确保您有正确的SQL查询。我认为您需要首先检查您的流程,以便对此感觉更好。如果您对DB造成干扰,IT环境将是完全不友好的!您应该设法使您的测试环境与生产环境类似.如果您需要帮助设置测试数据库服务器(也许你们有一些奇怪的联合设置?),然后寻找它。这是一个很好的片段Marc,但我认为Hythloth正在寻找一种方法来撤销一个错误。比如说,他忘记了更新中的WHERE子句,并将表的所有列设置为一个值……哈哈……这就是他想要回滚的内容。好吧,你可以随时替换“提交事务”在我的代码片段中,使用另一个回滚,只需检查查询结果,然后无论如何回滚;类似于“假设”查询-应用它,查看结果,然后无论如何仍然回滚+1:如果“被询问”,这是您能做的最多的事情在生产数据库上执行此操作;此外,确保您有一个易于访问/恢复的备份这是我使用的,如果SELECT返回预期的行数,则继续进行更新或删除。我曾经向DBA提交了一个生产数据的数据更改请求,我的经理没有真正查看查询,而是批准了,DBA执行后,我公司的每个员工都被命名为“Tori M.”。我更改了E
begin tran

delete mt
--select * 
from mytable mt where <some condition>

--commit tran
--rollback tran

begin tran

update mt
set myfield = replace(myfield, 'some random text', 'some other random text'
--select myid, myfield, replace(myfield, 'some random text', 'some other random text'
from mytable mt where <some condition>

--commit tran
--rollback tran