由于主键约束导致的T-SQL存储过程异常

时间:2018-06-08 20:11:03

标签: sql-server tsql

我有一个存储过程将记录插入两个表中。

首先我将它插入tableA,然后插入tableB。

我有点困惑,因为如果插入到tableA失败,我希望它出错并且不运行下一个语句。但事实似乎并非如此......

如果发生异常,它仍会运行下面的语句吗?...

  BEGIN
      INSERT INTO TABLEA (Counter) VALUES (1989); -- duplicate error!
      INSERT INTO TABLEB (Counter) VALUES (2010);
  END

我得到的错误是:

  

违反PRIMARY KEY约束' PK_TABLEA'。无法在对象' dbo.TABLEA'中插入重复的密钥。重复键值是(1989)。声明已经终止。

我在C#控制台应用程序中调用此存储过程时遇到错误。这就是为什么我对提出异常的原因感到困惑的原因......但继续下一个陈述......

2 个答案:

答案 0 :(得分:2)

在TSQL中,您可以使用TRY / CATCH。发生错误时,后续操作可以继续运行并提交到表。

你现在这样做的方式:

CREATE TABLE #test1 (ID INT PRIMARY KEY)
GO 
CREATE TABLE #test2 (ID INT PRIMARY KEY)
GO 

BEGIN TRAN;
INSERT INTO #test1 (ID)
VALUES 
(1);

INSERT INTO #test2 (ID)
VALUES 
(1)
;
COMMIT

BEGIN TRAN;
INSERT INTO #test1 (ID)
VALUES 
(1);

INSERT INTO #test2 (ID)
VALUES 
(2);

COMMIT

SELECT * 
FROM #test1
SELECT * 
FROM #test2

使用try和catch块,可以防止在发生错误时发生这两个语句。

CREATE TABLE #test1 (ID INT PRIMARY KEY)
GO 

CREATE TABLE #test2 (ID INT PRIMARY KEY)
GO 


BEGIN TRAN;

INSERT INTO #test1 (ID)
VALUES 
(1);

INSERT INTO #test2 (ID)
VALUES 
(1)
;

COMMIT


BEGIN TRY
INSERT INTO #test1 (ID)
VALUES 
(1);

INSERT INTO #test2 (ID)
VALUES 
(2)

END TRY

BEGIN CATCH
print('bad things happened')
END CATCH


SELECT * 
FROM #test1
SELECT * 
FROM #test2

答案 1 :(得分:1)

此行为是早期版本的t-sql的遗留问题,并且不会破坏向后兼容性。

通过将属性let points = 8 //number of rectangles/2 var q = CGFloat(start) var bodies = [SKPhysicsBody]() for i in 1...(points*2) { let parc = UIBezierPath() parc.move(to: CGPoint(x: inner * cos(q), y: inner * sin(q))) parc.addLine(to: CGPoint(x: outer * cos(q), y: outer * sin(q))) q += (offset/CGFloat(points)) parc.addLine(to: CGPoint(x: outer * cos(q), y: outer * sin(q))) parc.addLine(to: CGPoint(x: inner * cos(q), y: inner * sin(q))) parc.close() bodies.append(SKPhysicsBody(polygonFrom: parc.cgPath)) } //adjusting code to allow a physics body from multiple physics body instead of one //shape.physicsBody = SKPhysicsBody(polygonFrom: arc.cgPath) shape.physicsBody = SKPhysicsBody(bodies: bodies) 设置为

,可以实现更具结果性和可预测性的行为
XACT_ABORT

关于此错误处理相关内容的一篇非常好的文章: http://www.sommarskog.se/error_handling/Part1.html

相关文章讨论了与存储过程相关的内容: What is the benefit of using "SET XACT_ABORT ON" in a stored procedure?

这还包括在执行包含多个命令或涉及事务的tsql脚本之前始终设置XACT_ABORT ON的建议。