我需要在 Sql Server 上模拟错误:
“Msg 0, Level 20 A severe error occurred on the current command”
因为我们的开发人员必须在应用程序中处理它。
如何模拟/触发这种错误?(我也可以在我的本地主机上尝试)。
我需要在 Sql Server 上模拟错误:
“Msg 0, Level 20 A severe error occurred on the current command”
因为我们的开发人员必须在应用程序中处理它。
如何模拟/触发这种错误?(我也可以在我的本地主机上尝试)。
假设您尝试运行以下查询:
SELECT *
FROM dbo.Customers c
WHERE id = @id
AND dateTimeCreated = @date
您将收到一条错误消息,如下所示Must declare the scalar variable "@id".
据我了解,这发生在查询的初始解析期间,在执行任何代码之前。
是否可以让 SQL Server 一次报告所有丢失的变量,或者这正是查询解析器的工作方式?
DECLARE @Error int;
INSERT INTO Person.BusinessEntityContact
(BusinessEntityID
,PersonID
,ContactTypeID)
VALUES
(0,0,1);
SELECT @Error = @@ERROR;
PRINT ‘The Value of @Error is ‘ + CONVERT(varchar, @Error);
我有 :
消息 547,级别 16,状态 0,第 4 行 INSERT 语句与 FOREIGN KEY 约束“FK_BusinessEntityContact_Person_PersonID”冲突......该语句已终止。@Error 的值为 547
这意味着在抛出错误后该过程仍在继续。
但是,如果我尝试创建一个表(运行下面的脚本两次以触发错误)为:
CREATE TABLE OurIFTest(
Col1 int PRIMARY KEY
);
IF @@ERROR != 0
PRINT 'Problems!';
ELSE
PRINT 'Everything went OK!';
然后我得到了
消息 2714,级别 16,状态 6,第 2 行数据库中已经有一个名为“OurIFTest”的对象。
这意味着在抛出错误时进程终止。
那么为什么进程因“创建”而不是“插入”而终止?
在传统编程中,有一条公理表明“不要使用错误来进行流控制”。一个普遍的例子是抛出一个错误然后捕获错误,而不是使用普通的条件语句或中断语句。这是有害的,因为应用程序必须展开调用堆栈并调用一些相对昂贵的异常处理逻辑,而不是简单地处理条件语句。
我正在使用一个 postgres 系统,其中用户在 postgres 中调用一个函数,该函数在不满足条件时抛出错误而不是不返回任何行。条件大致是“这个输入值不存在,无事可做”而不是真正的例外情况。
当以类似于传统编程的方式抛出错误时,postgres 是否会产生运行时成本?换句话说,在 postgres 中使用异常作为流控制对性能有害还是马虎?
我喜欢在我的编码中冗长,所以我的典型插入语句如下所示:
INSERT INTO MyTable
(
Column1
,Column2
,Column3
,Column4
,Column5
,Column6
)
SELECT
Column1 = 'some value'
,Column2 = 'some value'
,Column4 = 'some value'
,Column3 = 'some value'
,Column5 = 'some value'
,Column6 = 'some value'
....
如果你没有注意到这句话的问题,那么你就和我一样被愚弄了无数次。
而这类缺陷真正阴险的部分是,它可能会在导致任何问题之前工作很长时间,当它失败时,即使有错误,它也不会指示真正的错误。
例如,如果第 3 列和第 4 列分别是数字和字符串类型,那么只有某些值会导致第 4 列出现运行时错误(而第 3 列不会出现运行时错误)类型转换失败(例如,'0' 转换为数字就好了但 'asdf' 不会)。
(在我的例子中,它被隐藏在受保护代码部分之外的 Service Broker 激活过程中(这是一个日志语句),所以我什至没有看到那个错误,而是得到了伪装成禁用我的队列的毒消息的孤立事务错误。)
有什么方法可以验证这种不需要人工校对的说法吗?
PS 我知道你可以给任何你喜欢的别名,但是在一个完全可选的上下文中,比如一个语句,使用某种自动化工具(即 IntelliSense)来指出可能的意外代码INSERT
将是非常有用的。
更新:我已经向微软开放了这个反馈项目,因为这个明显缺乏的功能。
我有一个包含多个索引的表。在我的应用程序代码中,可能会出现违反这些索引中的任何一个的情况,具体取决于用户输入。
当我的 PL/SQL 代码偶然发现一个ORA-00001
.
有没有办法知道哪个索引违规导致 Oracle 引发dup_val_on_index
?
在编写程序时,我偶尔会遇到想要中止程序的情况,即使这种情况不一定会触发错误。
比方说,如果我不想让 John 能够运行这个过程,我会做这样的事情:
IF @UserName = 'John'
BEGIN
RAISERROR('John, get out', 16, 1);
RETURN 1;
END
我真的没有理由返回 1,它主要是 shell 脚本的残余,我愿意寻找更好的方法来做到这一点。
有没有更好的方法来返回错误消息并将控制权返回给调用者,以应对严格来说不是错误的意外情况?我对减少字符或代码行的数量不感兴趣。我只是有一种直觉说“这可能不是解决这个问题的最佳方法”,我很好奇是否有更聪明的方法来做到这一点。
一种替代方法是始终使用TRY/CATCH
,因为RAISERROR
严重性为 1-19 会将控制权交给 catch 子句。
例子:
BEGIN TRY
PRINT 'Before RAISERROR';
RAISERROR('Time for errors', 16, 1);
PRINT 'After RAISERROR'
END TRY
BEGIN CATCH
DECLARE @Msg NVARCHAR(255) = ERROR_MESSAGE()
PRINT 'Inside CATCH'
RAISERROR(@Msg, 16, 1)
END CATCH
输出:
Before RAISERROR
Inside CATCH
Msg 50000, Level 16, State 1, Line 13
Time for errors
缺点:需要TRY/CATCH
块的存在。
当我的一个进程对我们用于预处理目的的临时表执行批量加载时,我遇到过几次问题。批量加载由于某种原因而失败(我们正在单独研究和解决),然后我们批量加载的表被锁定。Quiesce/Unquiesce 甚至重新启动 DB2 都不会释放该表上的锁。
这是我们每次收到的相关错误的屏幕截图:
此错误代码表示该表处于“加载挂起”状态。先前对此表的 LOAD 尝试导致失败。在重新启动或终止 LOAD 操作之前,不允许访问该表。
是否有任何命令或方法可以规避此问题或重新获得对该特定表的访问权限?当这个批量加载运行时,我们还有许多其他进程正在运行,因此重新启动 DB2 是一个非常不受欢迎的选项,并且在我们现在的情况下,它还没有释放表。
抱歉,如果这没有足够的信息可以关闭,请让我知道如果需要我还应该提供什么。
我的部门目前严重依赖 SQL Server 作业中的 CmdExec 步骤,称为使用 SQL Server 登录。
例如
osql /e /n /S SERVER01 /U USER /P PA$$$ /d DATABASE_01 /i "\\LOCATION\OF\SQL\SCRIPT\scriptfile.sql" /o "\\LOCATION\OF\SQL\LOG\scriptfile.log"
出于很多原因(尤其是安全性和预期此方法将过时),我希望我们放弃此模型并替换为存储过程和 SSIS 包的混合体。
我已经多次提出这个建议,我总是被告知,如果我们可以通过上述方法重新创建可能的日志记录细节,我们只能朝这个方向前进,我们的部门已经非常依赖这种方法。上面的方法在上下文中输出脚本的内容以及任何服务器消息,包括所有行数和错误消息。
诚然,这确实意味着对于 SQL Server 而言不算作错误的错误更容易被拾取 - 意外的低行数等。您可以根据需要进行尽可能多的错误处理,并且永远不会像从这个方法记录,所以我可以看到参数的这一面。
为了让我的老板远离 cmdexec 步骤,我想找到一种方法来重新创建类似于 cmdexec 当前提供给我们的日志记录输出的方法 - 也许是 SQL 表而不是文件(尽管两者都可以) - 在SSIS 包和存储过程。
我熟悉使用 raiserror 进行错误处理——我在存储过程中广泛使用它——但这里的任务不仅仅是捕获 SQL 错误,而是捕获所有 cmdexec 日志记录捕获,最好是在正在执行的脚本的上下文中。 . 除了编写存储过程并在每个脚本的每个步骤之后执行它之外,我看不到这样做的方法。
此外,我很想听听有关为不使用 cmdexec 步骤的人进行日志记录的最佳实践方法。我在这个部门学习过 SQL,这是我所知道的唯一做事方式。
为了我自己的开发,我越来越多地尝试编写带有错误处理的存储过程。如果我遇到不会引发错误的问题,我会通过在开发服务器上以交互方式重新运行代码来进行故障排除,这样我就可以监控分步信息。这不如我们从 cmdexec 获得的完整日志记录方便,但更安全。
其他人做的比这更多吗?有没有更好的办法?
我有一个设置脚本调用sp_configure
几次来设置一些系统变量,它工作正常但我有以下几个语句
配置选项 '%ls' 从 %ld 更改为 %ld。运行 RECONFIGURE 语句进行安装。
相应地填充变量。在内部我可以看到 sp_configure 正在调用
raiserror(15457,-1,-1, @configname, @prevvalue, @configvalue) with log
当用户运行脚本时,我能做些什么来防止这些信息性消息(对脚本无用,我RECONFIGURE
从脚本内部调用)显示在 MSSMS 的消息窗口中?