Julia :
Alors, qui a changé ma procédure hier?Lesha :
pas moiMaxim :
pas moi- Les
gars, pouvons-nous obtenir Git?Seryozha :
il est grand temps!2 semaines se sont écoulées ...
Julia : les
gars?-
Yul, tu ne t'es pas engagé?Julia :
bon sang non (...Voilà comment tout a commencé. Eh bien, quoi, chaque personnage et chaque ligne s'engagent?
Ou peut-être que tout cela se produira tout seul?) À ce stade, ils commencent à penser
Des déclencheurs DDL , une
table temporelle et une image sont ajoutés. Résolu, nous allons stocker des versions à l'intérieur
SQL Server'a !)

Tout d'abord, créez des tables dans lesquelles les versions seront stockées
USE master GO
Il est important de garder à l'esprit les limites de la
table temporelle.- Après les avoir créés, vous ne pouvez pas appliquer de commandes DDL aux tables principales ou historiques. Et vous ne pouvez pas supprimer la table temporelle
- Vous ne pouvez pas modifier les données du tableau historique
La deuxième restriction nous convient, mais que faire de la première?
L'algorithme est le suivant:
Bien qu'il n'y ait pas encore d'index sur la table, remplissez-la avec nos procédures, fonctions, etc. marquées
INIT , ce qui dans notre cas signifiera le placement initial
DECLARE @query NVARCHAR(MAX), @template NVARCHAR(MAX) = N' USE [db] INSERT INTO MASTER.dbo.VersionControl WITH (TABLOCKX) ( Event, Db, Sch, Object, Sql, Login ) SELECT ''INIT'' AS Event, DB_NAME(), ss.name AS Sch, so.name AS Object, CONCAT(''<query><![CDATA['', sasm.definition, '']]></query>'' ), SUSER_SNAME() AS Login FROM sys.objects AS so JOIN sys.schemas AS ss ON ss.schema_id = so.schema_id JOIN sys.all_sql_modules AS sasm ON sasm.object_id = so.object_id WHERE so.is_ms_shipped = 0 AND NOT EXISTS ( SELECT 1 FROM MASTER.dbo.VersionControl AS vc WHERE vc.Db = ''[db]'' AND vc.Sch = ss.name AND vc.Object = so.name ); '; DECLARE @databases TABLE (rn INT, Name sysname); INSERT @databases (rn, Name) SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn, name FROM sys.databases WHERE owner_sid != 0x01; DECLARE @i INT = 1, @max INT = (SELECT MAX(rn) FROM @databases), @error NVARCHAR(128), @db sysname; WHILE @i < @max BEGIN SELECT @query = REPLACE(@template, '[db]', Name), @db = Name FROM @databases WHERE rn = @i; BEGIN TRY EXECUTE sp_executesql @query; SET @i += 1; CONTINUE; END TRY BEGIN CATCH SET @error = CONCAT( 'XML Parsing error. In this case that''s mean one of [', @db, '] object is invalid for convert to XML' ); PRINT @error; SET @i += 1; CONTINUE; END CATCH; END; GO
Parce que les modifications apportées aux objets se produiront avec l'
instruction UPDATE , et nous examinerons le plus souvent les versions par clé: la base de données, le schéma et le nom de l'objet, l'index supplie!
IF NOT EXISTS ( SELECT 1 FROM sys.indexes WHERE name = 'IX_VersionControl_upd_key' ) CREATE UNIQUE NONCLUSTERED INDEX IX_VersionControl_upd_key ON MASTER.dbo.VersionControl (Db, Sch, Object) INCLUDE (Sql, Event, Login);
Tout est prêt pour commencer à stocker des versions et nous aidera avec ce
déclencheur DDLImportant! Parce que les tables pour les versions sont dans la base de données
master , après avoir créé un déclencheur, tous ceux qui n'ont pas les droits sur cette base de données ne peuvent pas modifier, créer ou supprimer des objets
IF EXISTS ( SELECT 1 FROM sys.server_triggers WHERE name = 'tr_VersionControl' ) DROP TRIGGER tr_VersionControl ON ALL SERVER GO CREATE TRIGGER tr_VersionControl ON ALL SERVER
Et pour la commodité de l'utilisation de ce système, la procédure ci-dessous est proposée.
C'est simple à utiliser. Le préfixe
sp_ nous aidera à accéder à la procédure sans spécifier la base de données et le schéma. Les paramètres sont remplis intuitivement. Vous pouvez spécifier uniquement la base de données et nous verrons les objets qui lui sont associés uniquement pendant tout le temps, mais vous pouvez également utiliser le schéma, l'objet lui-même et bien sûr la plage de temps pour laquelle des modifications ont été apportées.
CREATE PROCEDURE dbo.sp_Vc @db sysname = '%', @sch sysname = '%', @obj sysname = '%', @from DATETIME2(0) = NULL, @to DATETIME2(0) = NULL AS BEGIN SET NOCOUNT ON; IF @from IS NULL AND @to IS NULL BEGIN SELECT * FROM master.dbo.VersionControl WHERE Db LIKE @db AND Sch LIKE @sch AND Object LIKE @obj ORDER BY StartDate DESC END ELSE BEGIN SELECT * FROM master.dbo.VersionControl FOR SYSTEM_TIME BETWEEN @from AND @to WHERE Db LIKE @db AND Sch LIKE @sch AND Object LIKE @obj ORDER BY StartDate DESC END END GO
Voici des exemples d'utilisation de la procédure
Vous pouvez installer ce microframework à partir de mon
référentiel , et si votre version de SQL Sever est plus récente que 2016, alors vous y
êtes . Soit dit en passant, nous utilisons cette version maintenant, mais ce n'est pas si cool.
En conclusion
Je n'ai jamais réussi à vaincre la conclusion
& _gt; et
& _lt; au lieu des signes
> et
< de la table
master.dbo.VersionControl par le champ
Sql . Si vous pouvez nous aider ou si vous avez des idées, j'attends une
demande de tirage .
Merci pour votre temps, mettez des étoiles, des cœurs et des flèches.