【问题标题】:I'm getting an error message but it exec fine?我收到一条错误消息,但它执行得好吗?
【发布时间】:2021-04-19 19:31:39
【问题描述】:
IF EXISTS (SELECT name
           FROM sys.tables
           WHERE name = 'Nums')
BEGIN
    DROP TABLE dbo.Nums;
END

CREATE TABLE dbo.Nums
(
     number INT NOT NULL, 
     CONSTRAINT PK_Nums PRIMARY KEY CLUSTERED(number ASC),
     code Char(9),
     date DATETIME
) ON [PRIMARY] 
    
INSERT INTO Nums (number, code, date)
VALUES (0, 485658235, '2000/01/01')

DECLARE @number int, @code Char(9), @date datetime

SET @number = (SELECT MAX (Number) FROM nums)
SET @date = (SELECT Date FROM Nums)
SET @code = (SELECT code FROM Nums)

WHILE @number < 100000
BEGIN
    INSERT INTO Nums--(number, code, date)
    VALUES (@number, @code, @date)

    SET @number = @number + 1
    SET @date = DATEADD(DAY, 5, @date)
    SET @code = LEFT(CAST(CAST(CEILING(RAND()* 10000000000) AS bigint) AS varchar),9) 
END

SELECT * FROM Nums

这是我得到的错误:

消息 2627,第 14 级,状态 1,第 41 行
违反主键约束“PK_Nums”。无法在对象“dbo.Nums”中插入重复键。重复键值为 (0)

【问题讨论】:

  • 错误在这里告诉你问题;你不明白错误怎么办?另外,你为什么使用WHILE 是通过痛苦的行来执行插入行? SQL 是一种基于集合的语言;计数会比这快得多。
  • 好吧 - 在创建插入一行 number = 0 的表之后,您就有了第一个 INSERT 语句。然后您的 WHILE 循环选择该数字,并且 again 尝试插入相同的值 - 这是 NOT 工作 - 按照设计。$
  • 这个485658235 是一个数字文字。不要强迫数据库引擎为您隐式转换它——这样的代码很脆弱并且容易出错。名为Date 的列被定义为日期时间 - 这与名称相矛盾。您插入的值是没有时间的日期(使用不寻常的格式 - 这是另一个问题)。如果您只想存储日期,则只需使用 DATE 数据类型。不要鼓励未来出现数据问题。

标签: sql-server while-loop


【解决方案1】:

您需要在循环开始前将数字加 1。

错误Violation of PRIMARY KEY constraint 通常不会批量中止,因此将继续执行下一条语句。

如果您想停止这种情况,请强制批处理中止并回滚:SET XACT_ABORT ON(可能是个好主意),或使用TRY/CATCH

我假设你也意识到你的过程可以在一个语句中完成,通过加入一个计数表或函数(例如,Itzik Ben-Gan 的these),如下所示:

INSERT @Nums (number, code, date)
SELECT
    t.Num,
    LEFT(CAST(CAST(CEILING(RAND()* 10000000000) AS bigint) AS varchar),9),
    '2000/01/01'
FROM fnTallyTable (0, 99999) t

【讨论】:

    猜你喜欢
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-14
    相关资源
    最近更新 更多