sql - 自动递增复合主键
问题描述
我正在研究一个包含事件表和违规表的数据库。事件表的主键是 IncidentID。那么违规表的主键就是 IncidentID,ViolationNum。
CREATE TABLE Incident (
IncidentID FLOAT,
Plate VARCHAR(10) NOT NULL,
PlateState INTEGER NOT NULL,
IncidentTypeID INTEGER NOT NULL,
CommonPlaceID INTEGER NOT NULL,
Officer INTEGER,
DateStart DATE NOT NULL,
DateEnd DATE,
Comments TEXT,
PRIMARY KEY (IncidentID),
FOREIGN KEY (Plate, PlateState) REFERENCES Vehicle (Plate, PlateState),
FOREIGN KEY (IncidentTypeID) REFERENCES IncidentTypeLookUp (IncidentTypeID),
FOREIGN KEY (CommonPlaceID) REFERENCES CommonPlace (CommonPlaceID),
FOREIGN KEY (Officer) REFERENCES Officer (BadgeNumber));
CREATE TABLE Violation (
IncidentID float,
ViolationNum INTEGER,
ViolationTypeID INTEGER NOT NULL,
DateOfViolation DATE NOT NULL,
Comments TEXT,
PRIMARY KEY (IncidentID,ViolationNum),
FOREIGN KEY (IncidentID) REFERENCES Incident (IncidentID),
FOREIGN KEY (ViolationTypeID) REFERENCES ViolationTypeLookUp (ViolationTypeID));
目标是让每个 IncidentID ex 的违规编号增加 1。2020001,1 2020001,2 2020001,3 2020002,1 2020002,2
我编写了以下触发器,每个触发器都有自己的错误。
create trigger violationCounter
on violation
instead of insert
as
begin
declare @iid float
declare @vnum int
declare @vtid int
declare @date date
declare @comm text
select @iid=IncidentID from inserted
select @vtid=ViolationTypeID from inserted
select @date = DateOfViolation from inserted
select @comm = comments from inserted
IF NOT EXISTS (Select * from Violation where IncidentID=@iid)
set @vnum = 1
else
set @vnum = (select max(ViolationNum)+1
from Violation
where IncidentID = @iid)
insert into Violation
values (@iid,@vnum,@vtid,@date,@comm)
end
go
此触发器不接受 Violation 作为 "@vnum=" select 语句中的对象。
或者
create trigger violationcounter
on Violation
instead of insert
as
begin
begin transaction
declare @iid float
declare @vnum int
IF EXISTS (Select * from Violation where @iid=IncidentID)
set @vnum = (select max(ViolationNum)+1
from Violation
where IncidentID = @iid);
else
set @vnum = 1;
INSERT INTO Violation (IncidentID,ViolationNum, ViolationTypeID,DateOfViolation,Comments)
SELECT IncidentID, @vnum, ViolationTypeID, DateOfViolation,Comments
FROM inserted
Commit transaction
end
此触发器被接受,但在输入数据时它不会增加违规编号。
我在这里到底做错了什么?
解决方案
正确的实现是使用序列或 IDENTITY 生成 ViolationNum,即使您将其保留为复合主键中的第二列。例如:
CREATE TABLE Violation (
IncidentID INTEGER,
ViolationNum INTEGER IDENTITY NOT NULL,
ViolationTypeID INTEGER NOT NULL,
DateOfViolation DATE NOT NULL,
Comments TEXT,
PRIMARY KEY (IncidentID,ViolationNum),
FOREIGN KEY (IncidentID) REFERENCES Incident (IncidentID),
FOREIGN KEY (ViolationTypeID) REFERENCES ViolationTypeLookUp (ViolationTypeID));
并且忘记为每个 IncidentID 重新开始的 ViolationNum 值。
推荐阅读
- android - 我在哪里可以找到启动应用程序的 android 源代码部分?
- javascript - 为什么我的程序在管理这个 JSON 文件时会崩溃?
- javascript - 在 React 中向用户呈现任何内容之前,如何从 API 或 Firebase 检索数据?
- c# - 拆分字符串并获取每个元素的子字符串
- wordpress - 更改主题位置 - WordPress
- python - 如何在python字典中添加日期时间
- android - 如何在 Ubuntu18.04 上运行 android_x86 系统(不是应用程序)作为 LXC 容器?(不要使用Anbox、VM工具,直接使用LCX)
- gpu - 至于 vulkan,GeForce RTX 3090 的 GPU 驱动程序不起作用
- python - Python 字符串格式
- java - Java ArrayDeque - offerLast & pollFirst vs offerFirst & pollLast