【问题标题】:SQL Where Exists Doesn't Filter?SQL Where Exists 不过滤?
【发布时间】:2013-02-07 04:50:52
【问题描述】:

System.Data.SqlClient.SqlException (0x80131904):违反 UNIQUE KEY 约束“AK_SeqNo”。无法在对象中插入重复键 'dbo.SeqNo'。

我随机收到上述 SQL Server 2005 Express 错误。从下面的存储过程中可能每 3 周一次。有谁知道为什么?

CREATE PROCEDURE [dbo].[mspResetSeqNo] @Today DATETIME
AS 
BEGIN
  SET NOCOUNT ON;

  DECLARE @DateSrc DATETIME
  DECLARE @MyGUID UNIQUEIDENTIFIER

  -- Check Input is Valid
  IF @Today IS NULL 
     BEGIN
           RAISERROR (N'@Today cannot be NULL', 10, 1); 
           RETURN 1;
     END

  -- Chop off the time part:
  SET @DateSrc = DATEADD(d, 0, DATEDIFF(d, 0, @Today));

  -- Get Current Location GUID
  SET @MyGUID = dbo.MyGUID();

  -- If this is the first entry for the day then initialise
  INSERT INTO dbo.SeqNo(MyGUID, TheDay, LastNo)
  SELECT @MyGUID, @DateSrc, 0
  WHERE NOT EXISTS ( 
      SELECT 1 FROM dbo.SeqNo AS sn
      WHERE sn.MyGUID = @MyGUID AND sn.TheDay = @DateSrc 
      );

  RETURN(0);
END

AK_SeqNo 的约束是:

ALTER TABLE [dbo].[SeqNo] ADD CONSTRAINT [AK_SeqNo] UNIQUE NONCLUSTERED 
(
[TheDay] ASC,
[MyGUID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

这两种数据类型的表列是:

[MyGUID] [dbo].[DForeignKey] NOT NULL,
[TheDay] [datetime] NOT NULL,

用户定义的类型 DForeignKey 是:

CREATE TYPE [dbo].[DForeignKey] FROM [uniqueidentifier] NULL

MyGUID() 函数只是检索本地系统 ID。每个位置都有不同的 ID。

CREATE FUNCTION [dbo].[MyGUID]()
RETURNS uniqueidentifier
AS
BEGIN
DECLARE @me as uniqueidentifier
SELECT @me = MyGUID FROM Self
RETURN @me
END

【问题讨论】:

  • AK_SeqNo 约束是如何定义的?
  • 我已经用这些详细信息更新了消息。
  • 表 dbo.SeqNo 上是否有触发器?
  • @TildalWave 例如2012-10-01 12:002012-10-01 14:00 是不同的DATETIME,但如果插入到同一个DATE 列中,它们就不是唯一的。
  • @TildalWave 我明白你在说什么,但这不是查询的 WHERE NOT EXISTS 部分的重点吗?如果 SeqNo 已经被初始化,那么不要插入。这在 99% 的情况下都能完美运行。

标签: sql sql-server tsql sql-server-2005-express


【解决方案1】:

问题是并发问题。单实例检查移至调用此存储过程的代码点之后。谢谢你的帮助。至少我又学到了 2 点关于 t-sql 函数的知识。

【讨论】:

    【解决方案2】:

    这是将记录添加到表中的唯一方法吗?

    我也会使用CONVERT 进行比较,如下所示:

      INSERT INTO dbo.SeqNo(MyGUID, TheDay, LastNo)
      SELECT @MyGUID, @DateSrc, 0
      WHERE NOT EXISTS ( 
          SELECT 1 FROM dbo.SeqNo AS sn
          WHERE sn.MyGUID = @MyGUID
          AND
          CONVERT(VARCHAR(11), sn.TheDay, 101) = CONVERT(VARCHAR(11), @Today, 101)
          );
    

    这使您不必将中间值存储在变量中。

    【讨论】:

      猜你喜欢
      • 2022-01-03
      • 2014-01-07
      • 2016-05-19
      • 2016-02-19
      • 2013-04-17
      • 1970-01-01
      • 2018-11-15
      • 1970-01-01
      • 2019-05-14
      相关资源
      最近更新 更多