Autor Téma: Reseeding pretekajici hodnoty IDENTITY rozsahu PK  (Přečteno 254 krát)

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 2928
  • Karma: 135
    • Verze Delphi: D2007, XE3, DX10
Reseeding pretekajici hodnoty IDENTITY rozsahu PK
« kdy: 29-05-2020, 08:06:53 »
Ahoj vsichni,

je to vicemene OT, ale treba ma nekdo nejaky napad, jak by se to dalo elegantne vyresit.

Mam tabulky napr. pro predikovane hodnoty na tyden dopredu po hodinach pro hafo velicin a kdyz jsem to navrhoval, tak jsem rozsah PK generovaneho jako IDENTITY posuzoval jen s ohledem na max. pocet zaznamu v tabulce, ale nedoslo mi, ze ten IDENTITY generator bude citat dal, i kdyz data budu prubezne mazat, takze neporostou. PK jsem zamerne udelal jen INTEGER (32bit), abych nezvetsoval objem dat, se kterym se pracuje a pracuje se s nimi hodne.

Fixnul jsem to tak, ze jsem skriptem smazal vsechny zaznamy v tabulce a prikazem CHECKIDENT udelal RESEED(1).

Ale v normalnim rezimu to nemazu vsechno naraz, aby kdyz dojde k nejakemu problemu s predikci jedne veliciny zustaly zachovany starsi predikce u vsech ostatnich, tedy smazu predikovane hodnoty jedne veliciny a vypoctu pro ni novou predikci.

Nenapada nekoho, jak do rezimu s nevyprazdnenou tabulkou zabudovat nejaky RESEED mechanismus? Asi bych mohl cekat na stav, kdy nejmensi hodnota IDENTITY bude vetsi nez maximalni pocet zaznamu s dostatecnou rezervou a udelat RESEED(1). Ale moc se mi to nelibi, protoze kdyz se neco vymkne a zustanou tam nejaka starsi data, tak se  takovy reseed mechanismus vypne.

Offline mmt

  • Nováček
  • *
  • Příspěvků: 15
  • Karma: 0
Re:Reseeding pretekajici hodnoty IDENTITY rozsahu PK
« Odpověď #1 kdy: 12-08-2020, 09:29:06 »
Ahoj,

odpovídám pozdě, ale třeba to pomůže. Šlo by místo identity použít SEQUENCE. Pak jde použít update a občas setřepat. Pokud je ID použito jako cizí klíč, pak je potřeba dočasně vypnout test klíče NOCHECK CONSTRAINT a aktualizovat i navázané tabulky.


Kód: [Vybrat]

CREATE SEQUENCE CountBy1 
    AS INT
    START WITH 1 
    INCREMENT BY 1 ;


CREATE TABLE Atable (
    ID INT DEFAULT NEXT VALUE FOR CountBy1 NOT NULL PRIMARY KEY
  , DT DATETIME2(7) NOT NULL DEFAULT SYSUTCDATETIME()
);

declare @Zmeny TABLE  (
    PuvodniID int
  , NoveID int
);

declare @ID int

INSERT INTO Atable DEFAULT VALUES;
ALTER SEQUENCE CountBy1 RESTART WITH 10000 ; 
INSERT INTO Atable DEFAULT VALUES;

INSERT INTO Atable DEFAULT VALUES;

SELECT * FROM Atable;

/*
update A SET
  ID=A.NoveID
from (select U.ID, ROW_NUMBER() OVER (order by U.ID) as NoveID from Atable U ) A
*/

--ALTER TABLE  NOCHECK CONSTRAINT
update A SET
  ID=A.NoveID
output deleted.ID as PuvodniID,inserted.ID as NoveID into @Zmeny
from (select U.ID, ROW_NUMBER() OVER (order by U.ID) as NoveID from Atable U ) A


SELECT * FROM Atable;
select * from @Zmeny

SET @ID=isnull((select max(ID) from Atable),1)+1

DECLARE @resetSQL nvarchar(255) = 'ALTER SEQUENCE CountBy1 RESTART WITH ' + convert(nvarchar(12),@ID);

exec sp_executesql @resetSQL;

INSERT INTO Atable DEFAULT VALUES;
INSERT INTO Atable DEFAULT VALUES;
SELECT * FROM Atable;