· 9 years ago · Nov 28, 2016, 11:54 AM
1create table File
2 (
3 id char(30) not null,
4 position int not null unique,
5 primary key (id)
6 );
7
8create table Cluster
9 (
10 id int not null,
11 next int not null, -- ми не можемо поÑтавити це поле unique бо -1 повторюєтьÑÑ
12 primary key (id)
13 );
14
15
16create procedure Copy
17 @fileId char(30)
18 as
19 begin
20 declare @curr int -- поточний елемент ланцюга Ñ–Ñнуючого файла
21 declare @prev int -- попепедній елемент Ñкщо він Ñ–Ñнує
22 declare @first int -- ми маємо запам'Ñтати початок
23 set @curr = (select position from File where id = @fileId)
24 set @prev = null
25 set @first = null
26
27 while @curr <> -1
28 begin
29 while 1 = 1 -- намагаємоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ транзакцію (вÑтавити Ñ€Ñдок поточного елемета ланцюга) поки вона не буде уÑпішною
30 begin
31 set transaction isolation level read uncommitted
32 begin transaction
33 begin try -- Ñкщо ми Ñпробуємо вÑтавити щоÑÑŒ на вже Ñ–Ñнуючий Ñ€Ñдок, то перейдемо в catch Ñ– будемо повторювати поки Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ буде уÑпішною
34 @declare lastId int -- перший Ñ–Ð½Ð´ÐµÐºÑ Ð¿Ð¾Ñ‡Ð¸Ð½Ð°ÑŽÑ‡Ð¸ з 0, Ñкий не зайнÑтий
35 set @lastId = 0
36 while exists (select * from Cluster where id = @lastId)
37 begin
38 set @lastId = @lastId + 1;
39 end
40
41 insert into Cluster -- Ñпробуємо зайнÑти цей Ñ€Ñдок копією елемента ланцюга
42 values (@lastId, -1)
43 if @prev <> null -- тільки Ñкщо Ñ–Ñнує попередній ми маємо проÑтавити його next на поточний
44 begin
45 update Cluster
46 set next = @lastId
47 where id = @prev
48 end
49 set @prev = @listId -- перехід
50 set @curr = (select next from Clister where id = @curr)
51 if @first = null
52 set @first = @lastId
53 waitfor delay '00:00:05'
54 commit
55 break
56 end try
57 begin catch
58 rollback transaction
59 continue
60 end catch
61 end
62 end
63 end
64 end
65
66 insert into File
67 values (@fileId + 'copy', @first)
68 end