【问题标题】:Transact-SQL / Check if a name already existsTransact-SQL / 检查名称是否已存在
【发布时间】:2011-03-31 02:28:05
【问题描述】:

这里是一个简单的问题。

上下文: 具有 int 主键的 Transact-SQL 表,并且名称也必须是唯一的(即使它不是主键)。比方说:

TableID INT,
TableName NVARCHAR(50)

我正在通过存储过程向此功能添加新行(因此,使用参数指定 TableName)。

问题:验证提供的 TableName 参数是否已存在于表中并防止添加新行的最佳/最简单方法是什么?

是否可以直接在我的 AddNewRow 存储过程中执行此操作?

【问题讨论】:

  • 您使用的是什么版本的 SQL Server?

标签: sql-server tsql sql-server-2008 merge


【解决方案1】:

TableName 上添加唯一约束并在尝试插入重复项时处理错误。

这避免了并发事务在您读取它不存在并尝试插入之间插入重复项的任何问题。

看到这个related question

【讨论】:

  • 完全有效的答案,我不得不承认,这是我想到的第一个答案。但它有一个重要的警告:它假设他可以更改数据库模式以添加这样的约束! :)
【解决方案2】:

我更喜欢在列上使用Unique Constraint,然后显式检查它的存在。

处理异常将导致身份增加(如果存在),

其次,可以通过在插入之前检查是否存在来避免异常,否则会是更昂贵的操作。

IF EXISTS (SELECT TOP(1) ColName FROM MyTable WHERE ColName=@myParameter)

如果使用唯一约束,您还可以应用Unique Nonclustured index,从而实现快速检索。

【讨论】:

  • 但这并没有考虑并发性。
  • @Martin:“账户并发”是什么意思。请解释一下,我没明白你的意思
  • 考虑“并发”而不是“帐户并发”:-) 如果没有任何额外的锁定提示,没有什么可以阻止 2 个事务读取它不存在并继续尝试插入。我猜想唯一约束无论如何都会阻止这种情况,但它仍在进行 2 次表访问,而不是 1 次。身份列中的差距应该无关紧要 - 如果他们这样做,那么 IDENTITY 无论如何都是错误的。所有唯一约束都由唯一索引支持。
  • @Martin:是的,我同意你的看法。不使用 Locking 会有并发问题。
【解决方案3】:

如果您使用的是 SQL Server 2008,那么您可以在存储过程中使用 MERGE 语句:

MERGE INTO YourTable AS target
USING (VALUES (@tableName)) AS source (TableName)
    ON target.TableName = source.TableName
WHEN NOT MATCHED THEN
    INSERT (TableName) VALUES (TableName)

您仍应确保TableName 列具有UNIQUE constraint

【讨论】:

  • 哦,是的。忘了那个。 +1 实际上,我过去也为此提供了 as an answer
  • 我可以像 if-else 一样同时使用 WHEN MATCHED 和 WHEN NOT MATCHED 语句吗?
  • @asmo - 是的。如果您想在匹配时更新并在不匹配时插入,您将包含这两个子句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
  • 2014-01-10
  • 2018-07-12
  • 2023-03-20
  • 2012-07-04
  • 1970-01-01
相关资源
最近更新 更多