首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >T-SQL以简单的方式向用户上报重复键异常

T-SQL以简单的方式向用户上报重复键异常
EN

Stack Overflow用户
提问于 2010-01-18 04:36:56
回答 2查看 1.3K关注 0票数 2

我有一个简单的country表,使用identity列作为主键。还有一些列用于包含2个字母和3个字母的ISO-3166国家/地区代码。这些列中的每一列都被定义为唯一索引。

在插入/更新时,我只想通知用户输入的ISO代码是否已在使用中。我依赖于数据库异常来触发这个过程。我不想用技术细节让用户不知所措。我只想告诉他输入的ISO值不能使用。

下面是我编写的Update存储过程中的T-SQL。它似乎很长,而且随着应用程序的增长和变化,它很容易出现将来的bug和/或持续的维护。有没有更好或更简单的方法?我可能对.net有点不熟悉,但我觉得这会更容易。

代码语言:javascript
复制
BEGIN TRY
  UPDATE [Country] SET [CountryName] = @CountryName, [CountryISO] = @CountryISO, [CountryISO3] = @CountryISO3, [UpdateDate] = @updateDate WHERE (([CountryID] = @CountryID) AND ([RowVersion] = @Original_RowVersion));
END TRY

BEGIN CATCH
  DECLARE @ErrSeverity int, @ErrNumber int, @ErrLine int
  DECLARE @ErrMsg nvarchar(4000)
  SELECT @ErrSeverity = ERROR_SEVERITY(), @ErrNumber = ERROR_NUMBER(),@ErrState = ERROR_STATE(),
         @ErrMsg = 
            CASE WHEN ERROR_NUMBER() = 2601
            THEN 
              CASE 
              WHEN ISNULL(CHARINDEX('IX_COUNTRYISO3', ERROR_MESSAGE()), 0) > 0
                THEN 'The 3 letter ISO-3166 value entered is already in use. Please enter a unique 3 letter ISO-3166 value.'
              WHEN ISNULL(CHARINDEX('IX_COUNTRYISO', ERROR_MESSAGE()), 0) > 0
                THEN 'The 2 letter ISO-3166 value entered is already in use. Please enter a unique 2 letter ISO-3166 value.'
              ELSE 
                ERROR_MESSAGE() + '(SQL ErrNo: ' + CONVERT(varchar(50), ERROR_NUMBER()) + ')' 
              END 
            ELSE 
              ERROR_MESSAGE() + '(SQL ErrNo: ' + CONVERT(varchar(50), ERROR_NUMBER()) + ')'
            END;
  RAISERROR(@ErrMsg, @ErrSeverity, @ErrState)
END CATCH

我的解决方案可行吗?

在插入和更新StoredProcs之间共享此异常代码的最佳方式是什么?

我想我本质上是在要求代码审查。

非常感谢你,迈克

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-01-18 04:54:51

我同意,这样的代码将成为令人头疼的维护问题。代码本身没有问题,只是问题被发现得太晚了。

唯一约束/索引是“最后一道防线”,至少在我的世界里是这样。如果您想提供良好的用户体验,您不能等到数据已经提交到数据库。您应该在UI级别主动检查重复项,并警告用户即将提交重复条目(如果不允许重复键,则禁用提交)。

如果最终提交了重复的键,这实质上说明了应用程序逻辑中的错误,所以数据库发出“类似数据库”的错误消息是可以接受的,您不需要试图美化它。应用程序应该尽可能优雅地处理此类错误,就像处理任何其他意外异常一样。

如果您只是简单地询问是否有一种方法可以在T-SQL中模块化这种功能……我不这样认为。无论如何,如果没有动态SQL的糟糕混乱,就不会有这样的问题。

SQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdateSQLUpdate-刚刚看到了对另一个答案的评论,如果你想在C#中重新获得错误号,那就足够简单了:

代码语言:javascript
复制
const int SqlDuplicateKeyError = 2601;

try
{
    db.Update(record);
}
catch (SqlException ex)
{
    switch (ex.Number)
    {
        case SqlDuplicateKeyError:
            // Custom error handling here
        default:
            throw;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2010-01-18 04:44:24

就我个人而言,我认为简单地给你的unqique约束/索引起一个合理而冗长的名字会比这更好。

如果用户直接与数据库交互,那么他们至少应该有一点IT知识。

如果用户通过自定义前端进行交互,那么您应该在前端实现错误处理。

要在前端捕获它,请参阅此link,这是一个基本的示例(可能充满错误)示例……

代码语言:javascript
复制
Catch (SqlExpcetion ex)
{
    if (e.Number == 2061 && ex.Message.Contains("IX_COUNTRYISO3")
    {
        MessageBox.Show("The 3 letter ISO-3166 value entered is already in use. Please enter a unique 3 letter ISO-3166 value.");
    }
    else
    {
         MessageBox.Show(String.Format("Error ({0}):{1}",ex.Number,ex.Message)
    }
}
Catch (Exception ex)
{
    MessageBox.Show(ex);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2082529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档