- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想基于自定义身份创建一个自定义身份。或类似于身份的功能,如自动递增 key 。
例如,如果我具有工程图的主键,则希望其修订基于工程图编号。
示例
DRAWINGID | REV | INFO------+-------+------1 | 0 | "Draw1"2 | 0 | "Draw2"2 | 1 | "Draw2Edit"2 | 2 | "Draw2MoreEdit"3 | 0 | "Draw3"4 | 0 | "Draw4"
If I was to insert a few more records into my table such a:
INSERT INTO DRAWING (INFO) VALUES ("Draw5")
INSERT INTO DRAWING (ID,INFO) VALUES (3,"Draw3Edit")
DRAWINGID | REV | INFO------+-------+------1 | 0 | "Draw1"2 | 0 | "Draw2"2 | 1 | "Draw2Edit"2 | 2 | "Draw2MoreEdit"3 | 0 | "Draw3"3 | 1 | "Draw3Edit" --NEW ROW4 | 0 | "Draw4"5 | 0 | "Draw5" --NEW ROW
T-SQL
CREATE TABLE DRAWING
(
ID INT,
REV INT,
INFO VARCHAR(50),
PRIMARY KEY (ID,REV)
);
CREATE TABLE CURRENT_DRAWING
(
ID INT IDENTITY (1,1),
DRAWING_ID INT,
DRAWING_REV INT,
PRIMARY KEY (ID),
FOREIGN KEY (DRAWING_ID,DRAWING_REV) REFERENCES DRAWING (ID,REV)
ON UPDATE CASCADE
ON DELETE CASCADE
);
DROP TABLE DRAW
GO
CREATE TABLE DRAW
(
ID INT DEFAULT(0),
REV INT DEFAULT(-1),
INFO VARCHAR(10),
PRIMARY KEY(ID, REV)
)
GO
CREATE TRIGGER TRIG_DRAW ON DRAW
FOR INSERT
AS
BEGIN
DECLARE @newId INT,
@newRev INT,
@insId INT,
@insRev INT
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRANSACTION
SELECT @insId = ID FROM inserted
SELECT @insRev = REV FROM inserted
PRINT 'BEGIN TRIG'
PRINT @insId
PRINT @insRev
PRINT @newId
PRINT @newRev
--IF ID=0 THEN IT IS A NEW ID
IF @insId <=0
BEGIN
--NEW DRAWING ID=MAX+1 AND REV=0
SELECT @newId = COALESCE(MAX(ID), 0) + 1 FROM DRAW
SELECT @newRev = 0
END
ELSE
--ELSE IT IS A NEW REV
BEGIN
--CHECK TO ENSURE ID EXISTS
IF EXISTS(SELECT * FROM DRAW WHERE ID=@insId AND REV=0)
BEGIN
PRINT 'EXISTS'
SELECT @newId = @insId
SELECT @newRev = MAX(REV) + 1 FROM DRAW WHERE ID=@insID
END
ELSE
--ID DOES NOT EXIST THEREFORE NO REVISION
BEGIN
RAISERROR 50000 'ID DOES NOT EXIST.'
ROLLBACK TRANSACTION
GOTO END_TRIG
END
END
PRINT 'END TRIG'
PRINT @insId
PRINT @insRev
PRINT @newId
PRINT @newRev
SELECT * FROM DRAW
UPDATE DRAW SET ID=@newId, REV=@newRev WHERE ID=@insId
COMMIT TRANSACTION
END_TRIG:
END
GO
INSERT INTO DRAW (INFO) VALUES ('DRAW1')
INSERT INTO DRAW (INFO) VALUES ('DRAW2')
INSERT INTO DRAW (ID,INFO) VALUES (2,'DRAW2EDIT1') --PROBLEM HERE
INSERT INTO DRAW (ID,INFO) VALUES (2,'DRAW2EDIT2')
INSERT INTO DRAW (INFO) VALUES ('DRAW3')
INSERT INTO DRAW (INFO) VALUES ('DRAW4')
GO
--SHOULD THROW
INSERT INTO DRAW (ID,INFO) VALUES (9,'DRAW9')
GO
SELECT * FROM DRAW
GO
Violation of PRIMARY KEY constraint
。
最佳答案
我实际上会推荐一种替代数据设计。这种键序列模式很难在关系数据库中正确实现,并且弊端往往大于 yield 。
您有很多选择,但是最简单的选择是将表一分为二:
CREATE TABLE DRAWING
(
ID INT IDENTITY(1, 1),
PRIMARY KEY (ID)
);
CREATE TABLE DRAWING_REVISION
(
ID INT IDENTITY(1, 1),
DRAWING_ID INT,
INFO VARCHAR(50),
PRIMARY KEY (ID),
CONSTRAINT FK_DRAWING_REVISION_DRAWING FOREIGN KEY (DRAWING_ID) REFERENCES DRAWING(ID)
);
DRAWING_REVISION
表中添加一行即可。因为主键使用
IDENTITY
规范,所以您不必做寻找下一个
ID
的工作。
ID
,则可以通过两种方式完成。它们都首先将
REV INT
和
DRAWING_REVISION
一起添加到
CONSTRAINT UK_DRAWING_REVISION_DRAWING_ID_REV UNIQUE (DRAWING_ID, REV)
的数据定义中。然后,诀窍当然是找出给定图纸的下一个修订号。
SELECT MAX(REV) + 1 FROM DRAWING_REVISION WHERE DRAWING_ID = @DRAWING_ID
触发器中简单地使用
INSTEAD OF INSERT
。但是,由于并发性高或运气不好,用户最终可能会互相阻塞,因为他们可能尝试将
DRAWING_ID
和
REV
的相同组合插入
DRAWING_REVISION
。
BEGIN TRAN
INSERT DRAWING DEFAULT VALUES;
INSERT DRAWING DEFAULT VALUES;
SELECT ID FROM DRAWING; -- Output: 1, 2
ROLLBACK TRAN
BEGIN TRAN
INSERT DRAWING DEFAULT VALUES;
SELECT ID FROM DRAWING; -- Output: 3
ROLLBACK TRAN
IDENTITY
值并增加计数器。如果您从未真正提交过该值,则服务器不会尝试“回填”序列中的孔-这些值仅在向前的基础上提供。
IDENTITY
列设计为有序且唯一,但不必紧密包装。保证紧密打包的唯一方法是序列化所有传入的请求,确保每个请求在下一个请求开始之前完成或终止。否则,服务器可能会尝试回填半小时前发出的
IDENTITY
值,只是为了使长时间运行的事务(即该
IDENTITY
值的初始接收者)提交具有重复主键的行。
TRANSACTION
。它绝对可以是应用程序或SQL Server端上的任何过程,可能花费任何数量时间,即使该时间仅是
SELECT
下一个修订版号,然后立即
INSERT
新
DRAWING_REVISION
所花费的时间。)
INSERT
请求的情况下,它将惩罚第二个提交请求。这迫使最后一个来者再次尝试(可能多次尝试,直到碰巧没有冲突为止)。一次有一个成功的提交:序列化,尽管没有队列的好处。
SELECT MAX(REV) + 1
方法具有相同的缺点。自然,
MAX
方法不会尝试回填值,但会强制每个并发请求争用相同的修订版号,并获得相同的结果。
IDENTITY
列执行SQL Server的操作:将它们分发出去,然后将它们扔掉。您可以使用类似以下SQL代码的代码,或使用等效的应用程序代码:
ALTER TABLE DRAWING ADD REV INT NOT NULL DEFAULT(0);
GO
CREATE PROCEDURE GET_REVISION_NUMBER (@DRAWING_ID INT) AS
BEGIN
DECLARE @ATTEMPTS INT;
SET @ATTEMPTS = 0;
DECLARE @ATTEMPT_LIMIT INT;
SET @ATTEMPT_LIMIT = 5;
DECLARE @CURRENT_REV INT;
LOOP:
SET @CURRENT_REV = (SELECT REV FROM DRAWING WHERE DRAWING.ID = @DRAWING_ID);
UPDATE DRAWING SET REV = @CURRENT_REV + 1 WHERE DRAWING.ID = @DRAWING_ID AND REV = @CURRENT_REV;
SET @ATTEMPTS = @ATTEMPTS + 1;
IF (@@ROWCOUNT = 0)
BEGIN
IF (@ATTEMPTS >= @ATTEMPT_LIMIT) RETURN NULL;
GOTO LOOP;
END
RETURN @CURRENT_REV + 1;
END
INSERT
事务的修订号,从而避免了对下一个
GET_REVISION_NUMBER
的调用。 (可以肯定地说,这是序列化的,但是仅用于需要以串行方式执行的过程的一小部分;与许多其他方法不同,该算法的其余部分可以自由地并行执行。)
SELECT MAX
情况下的冲突行为类似,但少得多。您可以将
SELECT MAX
方法(及任何相关方法)的有保证的连续编号换成可扩展性提高1000倍。这种权衡或多或少是基本的:据我所知,没有任何可以保证连续的,非序列化的解决方案。
DRAWING_REVISION.ID
即可。 (不过,如果您问我,以代理的方式公开代理键是不好的。)
关于sql - TSQL:通过自定义身份创建自定义身份吗? (管理数据库修订),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4472403/
前言: 有时候,一个数据库有多个帐号,包括数据库管理员,开发人员,运维支撑人员等,可能有很多帐号都有比较大的权限,例如DDL操作权限(创建,修改,删除存储过程,创建,修改,删除表等),账户多了,管理
所以我用 Create React App 创建并设置了一个大型 React 应用程序。最近我们开始使用 Storybook 来处理和创建组件。它很棒。但是,当我们尝试运行或构建应用程序时,我们不断遇
遵循我正在创建的控件的代码片段。这个控件用在不同的地方,变量也不同。 我正在尝试编写指令来清理代码,但在 {{}} 附近插入值时出现解析错误。 刚接触 Angular ,无法确定我错过了什么。请帮忙。
我正在尝试创建一个 image/jpeg jax-rs 提供程序类,它为我的基于 post rest 的 Web 服务创建一个图像。我无法制定请求来测试以下内容,最简单的测试方法是什么? @POST
我一直在 Windows 10 的模拟器中练习 c。后来我改用dev C++ IDE。当我在 C 中使用 FILE 时。创建的文件的名称为 test.txt ,而我给出了其他名称。请帮助解决它。 下面
当我们创建自定义 View 时,我们将 View 文件的所有者设置为自定义类,并使用 initWithFrame 或 initWithCode 对其进行实例化。 当我们创建 customUITable
我正在尝试为函数 * Producer 创建一个线程,但用于创建线程的行显示错误。我为这句话加了星标,但我无法弄清楚它出了什么问题...... #include #include #include
今天在做项目时,遇到了需要创建JavaScript对象的情况。所以Bing了一篇老外写的关于3种创建JavaScript对象的文章,看后跟着打了一遍代码。感觉方法挺好的,在这里与大家分享一下。 &
我正在阅读将查询字符串传递给 Amazon 的 S3 以进行身份验证的文档,但似乎无法理解 StringToSign 的创建和使用方式。我正在寻找一个具体示例来说明 (1) 如何构造 String
前言:我对 C# 中任务的底层实现不太了解,只了解它们的用法。为我在下面屠宰的任何东西道歉: 对于“我怎样才能开始一项任务但不等待它?”这个问题,我找不到一个好的答案。在 C# 中。更具体地说,即使任
我有一个由一些复杂的表达式生成的 ILookup。假设这是按姓氏查找人。 (在我们简单的世界模型中,姓氏在家庭中是唯一的) ILookup families; 现在我有两个对如何构建感兴趣的查询。 首
我试图创建一个 MSI,其中包含 和 exe。在 WIX 中使用了捆绑选项。这样做时出错。有人可以帮我解决这个问题。下面是代码: 错误 error LGH
在 Yii 中,Create 和 Update 通常使用相同的形式。因此,如果我在创建期间有电子邮件、密码、...other_fields...等字段,但我不想在更新期间专门显示电子邮件和密码字段,但
上周我一直在努力创建一个给定一行和一列的 QModelIndex。 或者,我会满足于在已经存在的 QModelIndex 中更改 row() 的值。 任何帮助,将不胜感激。 编辑: QModelInd
出于某种原因,这不起作用: const char * str_reset_command = "\r\nReset"; const char * str_config_command = "\r\nC
现在,我有以下由 original.df %.% group_by(Category) %.% tally() %.% arrange(desc(n)) 创建的 data.frame。 DF 5),
在今天之前,我使用/etc/vim/vimrc来配置我的vim设置。今天,我想到了创建.vimrc文件。所以,我用 touch .vimrc cat /etc/vim/vimrc > .vimrc 所
我可以创建一个 MKAnnotation,还是只读的?我有坐标,但我发现使用 setCooperative 手动创建 MKAnnotation 并不容易。 想法? 最佳答案 MKAnnotation
在以下代码中,第一个日志语句按预期显示小数,但第二个日志语句记录 NULL。我做错了什么? NSDictionary *entry = [[NSDictionary alloc] initWithOb
我正在使用与此类似的代码动态添加到数组; $arrayF[$f+1][$y][$x+1] = $value+1; 但是我在错误报告中收到了这个: undefined offset :1 问题:尝试创
我是一名优秀的程序员,十分优秀!